在如何控制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 != ) {
sendEvent(KeyEvent.ACTION_DOWN, , 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 != ) {
sendEvent(KeyEvent.ACTION_UP, KeyEvent.FLAG_CANCELED);
}
if (mSupportsLongpress) {
removeCallbacks(mCheckLongPress);
}
break;
case MotionEvent.ACTION_UP:
final boolean doIt = isPressed();
setPressed(false);
if (mCode != ) {
if (doIt) {
sendEvent(KeyEvent.ACTION_UP, );
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=""
android:layout_weight=""
android:scaleType="center"
systemui:glowBackground="@drawable/ic_sysbar_highlight"
android:contentDescription="@string/accessibility_back"
/>

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

Android 如何Android中自定义Navigationbar的更多相关文章

  1. android代码优化----ListView中自定义adapter的封装(ListView的模板写法)

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4 ...

  2. Android中自定义样式与View的构造函数中的第三个参数defStyle的意义

    零.序 一.自定义Style 二.在XML中为属性声明属性值 1. 在layout中定义属性 2. 设置Style 3. 通过Theme指定 三.在运行时获取属性值 1. View的第三个构造函数的第 ...

  3. Android中自定义Activity和Dialog的位置大小背景和透明度等demo

    1.自定义Activity显示样式 先在res/values下建colors.xml文件,写入: <?xml version="1.0" encoding="utf ...

  4. Android开发如何在4.0及以上系统中自定义TitleBar

    本文将通过一个实例讲解怎么实现在4.0及以上系统版本中实现自定义TitleBar,这只是我自己找到的一种方法; xml布局文件 activity_main.xml <RelativeLayout ...

  5. Android中自定义Activity和Dialog的位置大小背景和透明度等

    1.自定义Activity显示样式 先在res/values下建colors.xml文件,写入: view plainprint? 1. <?xml version="1.0" ...

  6. Android中自定义veiw使用Java中的回调方法

    //------------------MainActivity----中---------------------------------- import android.os.Bundle;imp ...

  7. android开发:Android 中自定义View的应用

    大家好我们今天的教程是在Android 教程中自定义View 的学习,对于初学着来说,他们习惯了Android 传统的页面布局方式,如下代码: <?xml version="1.0&q ...

  8. android中自定义view构造函数ContentItemView(Context context, AttributeSet paramAttributeSet)的用处

    自己定义一个view <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:a ...

  9. Android中自定义组合控件

    Android中自定义控件的情况非常多,一般自定义控件可以分为两种:继承控件及组合控件.前者是通过继承View或其子类,重写方法实现自定义的显示及事件处理方式:后者是通过组合已有的控件,来实现结构的简 ...

随机推荐

  1. scroolspy滚动监听插件

    <nav id="nav" class="navbar navbar-default"> <a href="#" clas ...

  2. CF741DArpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths(DSU on tree)

    题目大意: 给定一个以1为根的树,每条路径上都有一个字符(a~v共22个)询问对于每一个子树内最长的路径上字母经排序后可以形成回文串的最长路径多长 解题思路: 假定给你一个字符串,如何判定其经打乱能否 ...

  3. JavaScript学习总结(6)——js弹出框、对话框、提示框、弹窗总结

    一.JS的三种最常见的对话框 [javascript] view plaincopy //====================== JS最常用三种弹出对话框 =================== ...

  4. ubuntu-安装中文拼音输入法

    一下内容转载自http://blog.chinaunix.net/uid-24410388-id-3501873.html 自己验证了可用.转载了,已留做日后使用 步骤: step1:安装ibus所需 ...

  5. 学习笔记:Vue——组件和Prop

    前言:这一篇是关于组件基础.组件注册.Prop等内容. 1.组件基础 01.组件是可复用的Vue实例 02.组件中的data选项必须是一个函数 03.一个组件默认可以有任意数量的prop 任何值都可以 ...

  6. 关于VUE的一些指令的介绍

    V-cloak 这是一个不常用的指令,出现这个指令的原因是因为有时候网络速度慢,还没加载完vue,代码就开始编译了,这个时候渲染出来的内容就可想而知了 <!DOCTYPE html> &l ...

  7. 【CS Round #46 (Div. 1.5) E】Ultimate Orbs

    [链接]链接 [题意] n个人从左到右站在一条直线上.每个人都有一个能力值g[i],然后每个人可以将相邻的一个人打败. 然后它的能力值能够增加相应的能力值(就是打败了的那个人的能力值). A能够打败B ...

  8. HorizontalListView中使用notifyDataSetChanged()和notifyDataSetInvalidated()

    今天在项目中用到了水平ListView控件HorizontalListView,也是我在网上找的个开源HorizontalListView直接在项目中使用.我是把HorizontalListView放 ...

  9. update进行跨表之间的更新

    有时我们可能须要多个表之间进行更新数据. 我们能够使用这个语句 UPDATE table1,table2 SET table1.column=table2.column, table1.column1 ...

  10. 学习easyui疑问(三)

    今天我学习easyui中碰到的还有一问题是:怎样创建一个表格? 首先,在easyui中文官网上提供的这样一种定义方式: <!--table--> <table id="tt ...