NavigationBar按钮的事件绑定" />
当前位置: 代码迷 >> Android >> NavigationBar按钮的事件绑定
  详细解决方案

NavigationBar按钮的事件绑定

热度:64   发布时间:2016-04-28 02:13:24.0
如何Android中自定义Navigationbar

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

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


NavigationBar的创建

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

try {            boolean showNav = mWindowManagerService.hasNavigationBar();            /// M: Support Smartbook Feature.            if (true) Log.v(TAG, "hasNavigationBar=" + showNav);            if (showNav) {                mNavigationBarView =                    (NavigationBarView) View.inflate(context, R.layout.navigation_bar, null);                mNavigationBarView.setDisabledFlags(mDisabled);                mNavigationBarView.setBar(this);                mNavigationBarView.setOnTouchListener(new View.OnTouchListener() {                    @Override                    public boolean onTouch(View v, MotionEvent event) {                        checkUserAutohide(v, event);                        return false;                    }});            }        } catch (RemoteException ex) {            // no window manager? good luck with that        }
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按钮事件的绑定

private void prepareNavigationBarView() {        mNavigationBarView.reorient();        mNavigationBarView.getRecentsButton().setOnClickListener(mRecentsClickListener);        mNavigationBarView.getRecentsButton().setOnTouchListener(mRecentsPreloadOnTouchListener);        mNavigationBarView.getHomeButton().setOnTouchListener(mHomeSearchActionListener);        mNavigationBarView.getSearchLight().setOnTouchListener(mHomeSearchActionListener);        updateSearchPanel();    }

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

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

public boolean onTouchEvent(MotionEvent ev) {        final int action = ev.getAction();        int x, y;        switch (action) {            case MotionEvent.ACTION_DOWN:                //Slog.d("KeyButtonView", "press");                mDownTime = SystemClock.uptimeMillis();                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);                }                if (mSupportsLongpress) {                    removeCallbacks(mCheckLongPress);                    postDelayed(mCheckLongPress, ViewConfiguration.getLongPressTimeout());                }                break;            case MotionEvent.ACTION_MOVE:                x = (int)ev.getX();                y = (int)ev.getY();                setPressed(x >= -mTouchSlop                        && x < getWidth() + mTouchSlop                        && y >= -mTouchSlop                        && y < getHeight() + mTouchSlop);                break;            case MotionEvent.ACTION_CANCEL:                setPressed(false);                if (mCode != 0) {                    sendEvent(KeyEvent.ACTION_UP, KeyEvent.FLAG_CANCELED);                }                if (mSupportsLongpress) {                    removeCallbacks(mCheckLongPress);                }                break;            case MotionEvent.ACTION_UP:                final boolean doIt = isPressed();                setPressed(false);                if (mCode != 0) {                    if (doIt) {                        sendEvent(KeyEvent.ACTION_UP, 0);                        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CLICKED);                        playSoundEffect(SoundEffectConstants.CLICK);                    } else {                        sendEvent(KeyEvent.ACTION_UP, KeyEvent.FLAG_CANCELED);                    }                } else {                    // no key code, just a regular ImageView                    if (doIt) {                        performClick();                    }                }                if (mSupportsLongpress) {                    removeCallbacks(mCheckLongPress);                }                break;        }        return true;    }

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

<com.android.systemui.statusbar.policy.KeyButtonView android:id="@+id/back"                android:layout_width="@dimen/navigation_key_width"                android:layout_height="match_parent"                android:src="@drawable/ic_sysbar_back"                systemui:keyCode="4"                android:layout_weight="0"                android:scaleType="center"                systemui:glowBackground="@drawable/ic_sysbar_highlight"                android:contentDescription="@string/accessibility_back"                />

在onTouch中方法通过sendEvent()方法来执行不同的keycode响应事件,该方法会创建一个包含keycode的KeyEvent对象封装,然后通过injectInputEvent()向InputManager插入一个事件,再发送出去。

  相关解决方案