zoukankan      html  css  js  c++  java
  • Android 如何Android中自定义Navigationbar

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

    NavigationBar的代码是放在... rameworksasepackagesSystemUI路径下面的。该路径下的工程主要负责手机中系统级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插入一个事件,再发送出去。

  • 相关阅读:
    POJ 2411 Mondriaan's Dream
    POJ 2505 A multiplication game
    HDOJ(HDU) 3949 XOR
    雅礼集训DAY 6 T1 xmasdag
    bzoj 2159: Crash 的文明世界
    如何查看Ubuntu版本
    Ubuntu如何安装谷歌Chrome浏览器
    使用nano编辑器进行查找和替换
    Ubuntu修改用户和root密码
    Anaconda/Conda创建环境时报错的解决方案
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/6022880.html
Copyright © 2011-2022 走看看