在如何控制android系统中NavigationBar 的显示与隐藏文章里简要地介绍了Navigationbar的背景知识,
NavigationBar的代码是放在... rameworksasepackagesSystemUI路径下面的。该路径下的工程主要负责手机中系统级UI的显示部分,如下图框中选中部分(包含其中的通知栏的显示),USB的连接,截屏等等。
navigationbar 的代码是在SystemUI工程SystemUI/src/com/android/systemui/statusbar/phone的路径下,其中navigationbar是由PhoneStatusBar.java类创建的。在该类的makeStatusBarView()方法下,可以看到创建Navigationbar的过程:
01.
try
{
02.
boolean
showNav = mWindowManagerService.hasNavigationBar();
03.
/// M: Support Smartbook Feature.
04.
if
(
true
) Log.v(TAG,
"hasNavigationBar="
+ showNav);
05.
if
(showNav) {
06.
mNavigationBarView =
07.
(NavigationBarView) View.inflate(context, R.layout.navigation_bar,
null
);
08.
09.
mNavigationBarView.setDisabledFlags(mDisabled);
10.
mNavigationBarView.setBar(
this
);
11.
mNavigationBarView.setOnTouchListener(
new
View.OnTouchListener() {
12.
@Override
13.
public
boolean
onTouch(View v, MotionEvent event) {
14.
checkUserAutohide(v, event);
15.
return
false
;
16.
}});
17.
}
18.
}
catch
(RemoteException ex) {
19.
// no window manager? good luck with that
20.
}
通过修改navigation_bar布局的方式来自定义NavigationBar的UI。在该layout文件中有这样一个类。com.android.systemui.statusbar.policy.KeyButtonView,它是系统定义的在NavigationBar上的按钮类(后面会讲到),点击会产生波纹的效果。
NavigationBarView主负责UI的初始化工作,实例化布局,根据屏幕方向先取正确的图片。
NavigationBar按钮上的事件绑定并不是在NavigationBarView里实现,而是在SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java类中完成的。
通过NavigationBarView对外提供的获取按钮接口来完成按钮的绑定:
01.
private
void
prepareNavigationBarView() {
02.
mNavigationBarView.reorient();
03.
04.
mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);
05.
mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPreloadOnTouchListener);
06.
mNavigationBarView.getHomeButton().setOnTouchListener(mHomeSearchActionListener);
07.
mNavigationBarView.getSearchLight().setOnTouchListener(mHomeSearchActionListener);
08.
updateSearchPanel();
09.
}
上面三个按钮都是KeyButtonView类,它们的事件响应过程都是在类本身里面完成的。它们通过onTouchEvent()方法来响应点击事件,
01.
public
boolean
onTouchEvent(MotionEvent ev) {
02.
final
int
action = ev.getAction();
03.
int
x, y;
04.
05.
switch
(action) {
06.
case
MotionEvent.ACTION_DOWN:
07.
//Slog.d("KeyButtonView", "press");
08.
mDownTime = SystemClock.uptimeMillis();
09.
setPressed(
true
);
10.
if
(mCode !=
0
) {
11.
sendEvent(KeyEvent.ACTION_DOWN,
0
, mDownTime);
12.
}
else
{
13.
// Provide the same haptic feedback that the system offers for virtual keys.
14.
performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
15.
}
16.
if
(mSupportsLongpress) {
17.
removeCallbacks(mCheckLongPress);
18.
postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout());
19.
}
20.
break
;
21.
case
MotionEvent.ACTION_MOVE:
22.
x = (
int
)ev.getX();
23.
y = (
int
)ev.getY();
24.
setPressed(x >= -mTouchSlop
25.
&& x < getWidth() + mTouchSlop
26.
&& y >= -mTouchSlop
27.
&& y < getHeight() + mTouchSlop);
28.
break
;
29.
case
MotionEvent.ACTION_CANCEL:
30.
setPressed(
false
);
31.
if
(mCode !=
0
) {
32.
sendEvent(KeyEvent.ACTION_UP, KeyEvent.FLAG_CANCELED);
33.
}
34.
if
(mSupportsLongpress) {
35.
removeCallbacks(mCheckLongPress);
36.
}
37.
break
;
38.
case
MotionEvent.ACTION_UP:
39.
final
boolean
doIt = isPressed();
40.
setPressed(
false
);
41.
if
(mCode !=
0
) {
42.
if
(doIt) {
43.
sendEvent(KeyEvent.ACTION_UP,
0
);
44.
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);
45.
playSoundEffect(SoundEffectConstants.CLICK);
46.
}
else
{
47.
sendEvent(KeyEvent.ACTION_UP, KeyEvent.FLAG_CANCELED);
48.
}
49.
}
else
{
50.
// no key code, just a regular ImageView
51.
if
(doIt) {
52.
performClick();
53.
}
54.
}
55.
if
(mSupportsLongpress) {
56.
removeCallbacks(mCheckLongPress);
57.
}
58.
break
;
59.
}
60.
61.
return
true
;
62.
}
01.
<com.android.systemui.statusbar.policy.KeyButtonView android:id=
"@+id/back"
02.
android:layout_width=
"@dimen/navigation_key_width"
03.
android:layout_height=
"match_parent"
04.
android:src=
"@drawable/ic_sysbar_back"
05.
systemui:keyCode=
"4"
06.
android:layout_weight=
"0"
07.
android:scaleType=
"center"
08.
systemui:glowBackground=
"@drawable/ic_sysbar_highlight"
09.
android:contentDescription=
"@string/accessibility_back"
10.
/>
在onTouch中方法通过sendEvent()方法来执行不同的keycode响应事件,该方法会创建一个包含keycode的KeyEvent对象封装,然后通过injectInputEvent()向InputManager插入一个事件,再发送出去。
http://www.it165.net/pro/html/201503/35530.html