如何Android中自定义Navigationbar

在如何控制android系统中NavigationBar 的显示与隐藏文章里简要地介绍了Navigationbar的背景知识,

NavigationBar的代码是放在... rameworksasepackagesSystemUI路径下面的。该路径下的工程主要负责手机中系统级UI的显示部分,如下图框中选中部分(包含其中的通知栏的显示),USB的连接,截屏等等。

如何Android中自定义Navigationbar_第1张图片

NavigationBar的创建

navigationbar 的代码是在SystemUI工程SystemUI/src/com/android/systemui/statusbar/phone的路径下,其中navigationbar是由PhoneStatusBar.java类创建的。在该类的makeStatusBarView()方法下,可以看到创建Navigationbar的过程:

 

view source print ?
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. }
WindowManagerService通过判断是否需要显示NavigationBar来决定是否需要创建NavigationBarView, NavigationBarView即为我们看到视图的view了,navigation_bar即为NavigationBarView实例化的layout,你可以在SystemUI工程下的layout文件夹下找到。

 

通过修改navigation_bar布局的方式来自定义NavigationBar的UI。在该layout文件中有这样一个类。com.android.systemui.statusbar.policy.KeyButtonView,它是系统定义的在NavigationBar上的按钮类(后面会讲到),点击会产生波纹的效果。

NavigationBarView主负责UI的初始化工作,实例化布局,根据屏幕方向先取正确的图片。

NavigationBar按钮的事件绑定

NavigationBar按钮上的事件绑定并不是在NavigationBarView里实现,而是在SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java类中完成的。

通过NavigationBarView对外提供的获取按钮接口来完成按钮的绑定:

Recent, Home, SearchLight按钮事件的绑定

 

view source print ?
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. }

 

Menu, Home, Back按钮事件的绑定:

 

上面三个按钮都是KeyButtonView类,它们的事件响应过程都是在类本身里面完成的。它们通过onTouchEvent()方法来响应点击事件,

 

view source print ?
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. }

mCode是用来判断该触摸是来自于哪个button,表示不同button的keycode在KeyEvent中类都有定义。该值在布局文件中通过获取navigationbar_view中的systemui:keycode属性来获得,下面是layout布局文件中back相应代码段:

 

 

view source print ?
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

你可能感兴趣的:(如何Android中自定义Navigationbar)