android 自定义home键,关于Android系统栏中back和home键的实现

本文基于Android8.1系统编写

一、背景

今天想实现自定义的back和home键,比着葫芦画瓢,把back和home键的部局抄过来了。但怎么也没找到back和home键的java功能实现部分。

后来度娘了一下才找到实现的原理。

参考链接:http://blog.chinaunix.net/uid-701715-id-3054850.html

自己也记录一下

二、按钮的组件类KeyButtonView

在部局中可以看到,back和home键用了一个自定义view,开始我还以为是为了实现按钮的动画效果才自定义了一个这个view,现在发现自己天真了!

KeyButtonView的核心在于,他定义了一个可设置的部局属性keyCode,用于设置按钮对应的键,如下back键的部局代码:

xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:systemui="http://schemas.android.com/apk/res-auto"

android:id="@+id/back"

android:layout_width="@dimen/navigation_key_width"

android:layout_height="match_parent"

android:layout_weight="0"

systemui:keyCode="4"

android:scaleType="fitCenter"

android:contentDescription="@string/accessibility_back"

android:paddingTop="15dp"

android:paddingBottom="15dp"

android:paddingStart="@dimen/navigation_key_padding"

android:paddingEnd="@dimen/navigation_key_padding"

1

2

3

4

5

6

7

8

9

10

11

12

13

14

xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:systemui="http://schemas.android.com/apk/res-auto"

android:id="@+id/back"

android:layout_width="@dimen/navigation_key_width"

android:layout_height="match_parent"

android:layout_weight="0"

systemui:keyCode="4"

android:scaleType="fitCenter"

android:contentDescription="@string/accessibility_back"

android:paddingTop="15dp"

android:paddingBottom="15dp"

android:paddingStart="@dimen/navigation_key_padding"

android:paddingEnd="@dimen/navigation_key_padding"

keyCode=”4″对应的为KeyEvent.KEYCODE_BACK键

在KeyButtonView的构造函数中,读取并保存了这个属性:

Java

public KeyButtonView(Context context, AttributeSet attrs, int defStyle) {

super(context, attrs);

//...省略前面的代码

mCode = a.getInteger(R.styleable.KeyButtonView_keyCode, 0);

//...省略后面的代码

}

1

2

3

4

5

6

7

publicKeyButtonView(Contextcontext,AttributeSetattrs,intdefStyle){

super(context,attrs);

//...省略前面的代码

mCode=a.getInteger(R.styleable.KeyButtonView_keyCode,0);

//...省略后面的代码

}

如此,在部局文件中设置的keyCode读到了类中

三、模拟发送按键

原理是,拦截onTouch事件,当按钮按下时发送keyCode的ACTION_DOWN操作,当按钮弹开时发送keyCode的ACTION_UP操作,完成一次按键的操作。

Java

public boolean onTouchEvent(MotionEvent ev) {

//...省略部分代码

switch (action) {

case MotionEvent.ACTION_DOWN:

mDownTime = SystemClock.uptimeMillis();

mLongClicked = false;

setPressed(true);

if (mCode != 0) {

sendEvent(KeyEvent.ACTION_DOWN, 0, mDownTime);

} else {

// Provide the same haptic feedback that the system offers for virtual keys.

performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);

}

playSoundEffect(SoundEffectConstants.CLICK);

removeCallbacks(mCheckLongPress);

postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout());

break;

case MotionEvent.ACTION_MOVE:

//...省略

case MotionEvent.ACTION_CANCEL:

//...省略

break;

case MotionEvent.ACTION_UP:

final boolean doIt = isPressed() && !mLongClicked;

setPressed(false);

// Always send a release ourselves because it doesn't seem to be sent elsewhere

// and it feels weird to sometimes get a release haptic and other times not.

if ((SystemClock.uptimeMillis() - mDownTime) > 150 && !mLongClicked) {

performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY_RELEASE);

}

if (mCode != 0) {

if (doIt) {

sendEvent(KeyEvent.ACTION_UP, 0);

sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);

} else {

sendEvent(KeyEvent.ACTION_UP, KeyEvent.FLAG_CANCELED);

}

} else {

// no key code, just a regular ImageView

if (doIt && mOnClickListener != null) {

mOnClickListener.onClick(this);

sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);

}

}

removeCallbacks(mCheckLongPress);

break;

}

return true;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

publicbooleanonTouchEvent(MotionEventev){

//...省略部分代码

switch(action){

caseMotionEvent.ACTION_DOWN:

mDownTime=SystemClock.uptimeMillis();

mLongClicked=false;

setPressed(true);

if(mCode!=0){

sendEvent(KeyEvent.ACTION_DOWN,0,mDownTime);

}else{

// Provide the same haptic feedback that the system offers for virtual keys.

performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);

}

playSoundEffect(SoundEffectConstants.CLICK);

removeCallbacks(mCheckLongPress);

postDelayed(mCheckLongPress,ViewConfiguration.getLongPressTimeout());

break;

caseMotionEvent.ACTION_MOVE:

//...省略

caseMotionEvent.ACTION_CANCEL:

//...省略

break;

caseMotionEvent.ACTION_UP:

finalbooleandoIt=isPressed()&&!mLongClicked;

setPressed(false);

// Always send a release ourselves because it doesn't seem to be sent elsewhere

// and it feels weird to sometimes get a release haptic and other times not.

if((SystemClock.uptimeMillis()-mDownTime)>150&&!mLongClicked){

performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY_RELEASE);

}

if(mCode!=0){

if(doIt){

sendEvent(KeyEvent.ACTION_UP,0);

sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);

}else{

sendEvent(KeyEvent.ACTION_UP,KeyEvent.FLAG_CANCELED);

}

}else{

// no key code, just a regular ImageView

if(doIt&&mOnClickListener!=null){

mOnClickListener.onClick(this);

sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);

}

}

removeCallbacks(mCheckLongPress);

break;

}

returntrue;

}

sendEvent函数,先构造KeyEvent对象,然后通过InputManager发送到系统,代码如下:

Java

void sendEvent(int action, int flags, long when) {

//...省略部分代码

final int repeatCount = (flags & KeyEvent.FLAG_LONG_PRESS) != 0 ? 1 : 0;

final KeyEvent ev = new KeyEvent(mDownTime, when, action, mCode, repeatCount,

0, KeyCharacterMap.VIRTUAL_KEYBOARD, 0,

flags | KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,

InputDevice.SOURCE_KEYBOARD);

InputManager.getInstance().injectInputEvent(ev,

InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);

}

1

2

3

4

5

6

7

8

9

10

voidsendEvent(intaction,intflags,longwhen){

//...省略部分代码

finalintrepeatCount=(flags&KeyEvent.FLAG_LONG_PRESS)!=0?1:0;

finalKeyEventev=newKeyEvent(mDownTime,when,action,mCode,repeatCount,

0,KeyCharacterMap.VIRTUAL_KEYBOARD,0,

flags|KeyEvent.FLAG_FROM_SYSTEM|KeyEvent.FLAG_VIRTUAL_HARD_KEY,

InputDevice.SOURCE_KEYBOARD);

InputManager.getInstance().injectInputEvent(ev,

InputManager.INJECT_INPUT_EVENT_MODE_ASYNC);

}

打赏

f69872ab5631b766bfb8c62b6b7d28fa.png微信扫一扫,打赏作者吧~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值