为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

在android的状态栏(statusbar)中增加menu,home和back快捷键的方法 改进

2018-04-29 30页 doc 80KB 8阅读

用户头像

is_729658

暂无简介

举报
在android的状态栏(statusbar)中增加menu,home和back快捷键的方法 改进在android的状态栏(statusbar)中增加menu,home和back快捷键的方法 改进 ;nbsp; 需要说明的是:刚入手android没几天,对系统还不算很熟悉,这篇文章是基于前一篇转帖 做的。只是觉得他的方法有些麻烦,而且改出来的效果也不是我想要的。 由于完全改了 status bar ,建议先做几张 png 图片,加到 Frameworks/base/core/res/res/drawable 下。最好做一张背景图,替换 statusbar_background.png 另外我又加了几张 icon...
在android的状态栏(statusbar)中增加menu,home和back快捷键的方法 改进
在android的状态栏(statusbar)中增加menu,home和back快捷键的方法 改进 ;nbsp; 需要说明的是:刚入手android没几天,对系统还不算很熟悉,这篇文章是基于前一篇转帖 做的。只是觉得他的方法有些麻烦,而且改出来的效果也不是我想要的。 由于完全改了 status bar ,建议先做几张 png 图片,加到 Frameworks/base/core/res/res/drawable 下。最好做一张背景图,替换 statusbar_background.png 另外我又加了几张 icon ,分别是 home menu 和 back 的正常和按下状态。 这些图片为: stat_home.png stat_home_pressed.png stat_back.png stat_back_pressed.png stat_menu.png stat_menu_pressed.png 修改步骤为: 一(    修改 xml 界面   1. 增加图标   当然,更改整个 status bar 避免不要要对源码大刀修一下。我的该法是:   修改 status bar 的 layerout 文件: Frameworks/base/core/res/res/layout/status_bar.xml 在原来的 linearlayout 中新增三个 image view   view plain copy to clipboard print ? <; LinearLayout   android:id = ";@+id/icons";        android:layout_width = ";fill_parent";        android:layout_height = ";fill_parent";        android:orientation = ";horizontal"; >;                 <; ImageView   android:id = ";@+id/status_home";                 &n bsp;   android:layout_width = ";wrap_content";                     android:layout_height = ";wrap_content";                     android:layout_gravity = ";top";                     android:paddingTop = ";6dip";                     android:paddingRight = ";10dip";                     android:paddingLeft = ";10dip";                     android:src = ";@drawable/stat_home";   />;           <; com.android.server.status.IconMerger   android:id = ";@+id/notificationIcons";            android:layout_width = ";0dip";            android:layout_weight = ";1";            android:layout_height = ";fill_parent";            android:layout_alignParentLeft = ";true";            android:paddingLeft = ";6dip";            android:gravity = ";center_vertical";            android:orientation = ";horizontal"; />;                     <; LinearLayout   android:id = ";@+id/statusIcons";            android:layout_width = ";wrap_content";            android:layout_height = ";fill_parent";            android:layout_alignParentRight = ";true";            android:paddingRight = ";6dip";            android:gravity = ";center_vertical";            android:orientation = ";horizontal"; />;                     <; ImageView   android:id = ";@+id/status_menu";                     android:layout_width = ";wrap_content";                     android:layout_height = ";wrap_content";                     android:layout_gravity = ";top";                     android:paddingTop = ";6dip";                     android:paddingLeft = ";10dip";                     android:paddingRight = ";10dip";                     android:src = ";@drawable/stat_menu";   />;                 <; ImageView   android:id = ";@+id/status_back";                     android:layout_width = ";wrap_content";                     android:layout_height = ";wrap_content";                     android:layout_gravity = ";top";                     android:paddingTop = ";6dip";                     android:paddingRight = ";10dip";                     android:paddingLeft = ";10dip";                     android:src = ";@drawable/stat_back";   />;       /LinearLayout>;    <;LinearLayout android:id=";@+id/icons"; android:layout_width=";fill_parent"; android:layout_height=";fill_parent"; android:orientation=";horizontal";>; <;ImageView android:id=";@+id/status_home"; android:layout_width=";wrap_content"; android:layout_height=";wrap_content"; android:layout_gravity=";top"; android:paddingTop=";6dip"; android:paddingRight=";10dip"; android:paddingLeft=";10dip"; android:src=";@drawable/stat_home"; />; <;com.android.server.status.IconMerger android:id=";@+id/notificationIcons"; android:layout_width=";0dip"; android:layout_weight=";1"; android:layout_height=";fill_parent"; android:layout_alignParentLeft=";true"; android:paddingLeft=";6dip"; android:gravity=";center_vertical"; android:orientation=";horizontal";/>; <;LinearLayout android:id=";@+id/statusIcons"; android:layout_width=";wrap_content"; android:layout_height=";fill_parent"; android:layout_alignParentRight=";true"; android:paddingRight=";6dip"; android:gravity=";center_vertical"; android:orientation=";horizontal";/>; <;ImageView android:id=";@+id/status_menu"; android:layout_width=";wrap_content"; android:layout_height=";wrap_content"; android:layout_gravity=";top"; android:paddingTop=";6dip"; android:paddingLeft=";10dip"; android:paddingRight=";10dip"; android:src=";@drawable/stat_menu"; />; <;ImageView android:id=";@+id/status_back"; android:layout_width=";wrap_content"; android:layout_height=";wrap_content"; android:layout_gravity=";top"; android:paddingTop=";6dip"; android:paddingRight=";10dip"; android:paddingLeft=";10dip"; android:src=";@drawable/stat_back"; />; <;/LinearLayout>;    这样做的好处就是简单。同时保证最右端是 home 按钮,最左端是 back 按钮,不受它本来的约束。这样 status bar 上即可看到这些按钮了。        图标的位置,可通过修改 paddingRight , paddingLeft 和 paddingTop 的值达到最佳视觉效果。   2. 修改 status bar 的高度。   既然要在 status bar 上增加那么几个按钮,当然是想要使用触摸操作的, android 自带的 status bar 高度太小,不适用。对于 7 寸屏的话, 50pixel 的高度应该是差不多了。 修改高度很简单,如我转的 shinning mm 的博文。 修改 frameworks/base/core/res/res/values/dimens.xml 的 status_bar_height 属性     <;!-- Height of the status bar -->;     <;dimen name=";status_bar_height";>;50dip<;/dimen>; 当然,如果相改 title 的高度,可以修改 Frameworks /base/core/res/res/values/themes.xml 中的 Window attributes 的 windowTitleSize 值,不过我觉得没必要,改了反倒不好看了 :)   编译运行一下:   view plain copy to clipboard print ? ~/donut$ source ./env.sh   ~/donut$ make –j8   ~/donut$ emulator –skin WVGA800   ~/donut$ source ./env.sh ~/donut$ make –j8 ~/donut$ emulator –skin WVGA800 , 看状态栏是不是改变了,     二 为按钮添加动态效果   添加动态效果,就是触摸按下 hilight ,松开或者移出后恢复的动作。这一块,我是通过修改 frameworks/base/services/java/com/android/server/status/StatusBarView.java 实现的。   1. 获取 statusbar 中新增加的 icon 的 handler 。   在类中新增加三个成员(这需要 import android.widget.ImageView; ):   view plain copy to clipboard print ? ImageView mHomeIcon;   ImageView mBackIcon;   ImageView mMenuIcon;   ImageView mHomeIcon; ImageView mBackIcon; ImageView mMenuIcon;        同时增加三个常量,表示这些 icon 对应的键值 ( 这需要 import android.view.KeyEvent;)   view plain copy to clipboard print ? public   static   final   int  RESV_KEY_HOME = KeyEvent.KEYCODE_HOME;   public   static   final   int  RESV_KEY_BACK = KeyEvent.KEYCODE_BACK;   public   static   final   int  RESV_KEY_MENU = KeyEvent.KEYCODE_MENU;;   public static final int RESV_KEY_HOME = KeyEvent.KEYCODE_HOME; public static final int RESV_KEY_BACK = KeyEvent.KEYCODE_BACK; public static final int RESV_KEY_MENU = KeyEvent.KEYCODE_MENU;;     在 onFinishInflate() 中,获得实际的对象: view plain copy to clipboard print ? mHomeIcon = (ImageView)findViewById(R.id.status_home);   mBackIcon = (ImageView)findViewById(R.id.status_back);   mMenuIcon = (ImageView)findViewById(R.id.status_menu);   mHomeIcon = (ImageView)findViewById(R.id.status_home); mBackIcon = (ImageView)findViewById(R.id.status_back); mMenuIcon = (ImageView)findViewById(R.id.status_menu);   这三个对象就是我们在 status_bar.xml 中添加的。   2. 添加触摸处理。 首先,应该判断是那个图标被按下,这个我们在 StatusBarView.Java 的 onTouchEvent 中 来判断。 这里,我做了一个小的按键状态,已方便处理按下、弹起和移出的动作。 首先增加两个状态成员: view plain copy to clipboard print ? int  mResvKeyState = -1;   //记住的上次按键状 态, -1为无状态。    int  mResvKeyCode  = -1;   //记住的上次按键值, -1为无状态。    int mResvKeyState = -1; //记住的上次按键状态, -1为无状态。 int mResvKeyCode = -1; //记住的上次按键值,-1为无状态。                 这样我的 onTouchEvent 就变成这样了: view plain copy to clipboard print ? @Override       public   boolean  onTouchEvent(MotionEvent event) {       if (mService.mExpanded== true  || mService.mTracking== true ){          if  (event.getAction() != MotionEvent.ACTION_DOWN) {   ;            mService.inter ceptTouchEvent(event);          }           return   true ;       }          if (mResvKeyState == - 1 )  // remembered key state, no reserve        {           switch (getResvKeyArea(event)){               case  RESV_KEY_HOME:               case  RESV_KEY_BACK:               case  RESV_KEY_MENU:               {                   mResvKeyState = event.getAction();                   mResvKeyCode  = getResvKeyArea(event);                      updateResvKeyIcon(mResvKeyState, mResvKeyCode);               }               break ;                              default :               if  (event.getAction() != MotionEvent.ACTION_DOWN) {                   mService.interceptTouchEvent(event);               }           }       }else {           mResvKeyState = event.getAction(); // new state                       if (mResvKeyState == MotionEvent.ACTION_MOVE){               if (mResvKeyCode != getResvKeyArea(event)){                   /* out of bound, resume the icon */                    updateResvKeyIcon(MotionEvent.ACTION_UP, mResvKeyCode);                                      mResvKeyCode  = -1 ;                   mResvKeyState = -1 ;               }           }else   if (mResvKeyState == MotionEvent.ACTION_UP){               updateResvKeyIcon(mResvKeyState, mResvKeyCode);               mResvKeyCode  = -1 ;               mResvKeyState = -1 ;           }else {               Log.d(TAG, ";state machine error! Never be here!"; );  ;          }       }                 return   true ;      }   @Override public boolean onTouchEvent(MotionEvent event) { if(mService.mExpanded==true || mService.mTracking==true){ if (event.getAction() != MotionEvent.ACTION_DOWN) { mService.interceptTouchEvent(event); } return true; } if(mResvKeyState == -1) // remembered key state, no reserve { switch(getResvKeyArea(event)){ case RESV_KEY_HOME: case RESV_KEY_BACK: case RESV_KEY_MENU: { mResvKeyState = event.getAction(); mResvKeyCode = getResvKeyArea(event); updateResvKeyIcon(mResvKeyState, mResvKeyCode); } break; default: if (event.getAction() != MotionEvent.ACTION_DOWN) { mService.interceptTouchEvent(event); } } }else{ mResvKeyState = event.getAction(); // new state if(mResvKeyState == MotionEvent.ACTION_MOVE){ if(mResvKeyCode != getResvKeyArea(event)){ /* out of bound, resume the icon */ updateResvKeyIcon(MotionEvent.ACTION_UP, mResvKeyCode); mResvKeyCode = -1; mResvKeyState = -1; } }else if(mResvKeyState == MotionEvent.ACTION_UP){ updateResvKeyIcon(mResvKeyState, mResvKeyCode); mResvKeyCode = -1; mResvKeyState = -1; }else{ Log.d(TAG, ";state machine error! Never be here!";); } } return true; } 里面用到的两个private方法简单实现如下: view plain copy to clipboard print ? private   int  getResvKeyArea(MotionEvent  event )   {       if (  ( event .getX() <;= mHomeIcon.getRight())         &;&; (event .getY() <;=  this .getHeight()) ){           return  RESV_KEY_HOME;       }       else   if (  ( event .getX() >;= mBackIcon.getLeft())         &;&; (event .getY() <;=  this .getHeight()) ){           return  RESV_KEY_BACK;       }       else   if (  ( event .getX() >;= mMenuIcon.getLeft())         &;&; (event .getY() <;=  this .getHeight()) ){           return  RESV_KEY_MENU;       }else            return  -1;   }      private   int  updateResvKeyIcon( int  state,  int  key)   {       if (key == RESV_KEY_BACK){           if (state == MotionEvent.ACTION_UP){               mBackIcon.setImageResource(com.android.internal .R.drawable.stat_back);           }else   if (state == MotionEvent.ACTION_DOWN){               mBackIcon.setImageResource(com.android.internal .R.drawable.stat_back_pressed);           }       }else   if (key == RESV_KEY_HOME){           if (state == MotionEvent.ACTION_UP){               mHomeIcon.setImageResource(com.android.internal .R.drawable.stat_home);           }else   if (state == MotionEvent.ACTION_DOWN){               mHomeIcon.setImageResource(com.android.internal .R.drawable.stat_home_pressed);           }       }else   if (key == RESV_KEY_MENU){           if (state == MotionEvent.ACTION_UP){               mMenuIcon.setImageResource(com.android.internal .R.drawable.stat_menu);           }else   if (state == MotionEvent.ACTION_DOWN){               mMenuIcon.setImageResource(com.android.internal .R.drawable.stat_menu_pressed);           }       }              return  0;   }   private int getResvKeyArea(MotionEvent event) { if( (event.getX() <;= mHomeIcon.getRight()) &;&; (event.getY() <;= this.getHeight()) ){ return RESV_KEY_HOME; } else if( (event.getX() >;= mBackIcon.getLeft()) &;&; (event.getY() <;= this.getHeight()) ){ return RESV_KEY_BACK; } else if( (event.getX() >;= mMenuIcon.getLeft()) &;&; (event.getY() <;= this.getHeight()) ){ return RESV_KEY_MENU; }else return -1; } private int updateResvKeyIcon(int state, int key) { if(key == RESV_KEY_BACK){ if(state == MotionEvent.ACTION_UP){ mBackIcon.setImageResource(com.android.internal.R.drawable.stat_back); }else if(state == MotionEvent.ACTION_DOWN){ mBackIcon.setImageResource(com.android.internal.R.drawable.stat_back_pressed); } }else if(key == RESV_KEY_HOME){ if(state == MotionEvent.ACTION_UP){ mHomeIcon.setImageResource(com.android.internal.R.drawable.stat_home); }else if(state == MotionEvent.ACTION_DOWN){ mHomeIcon.setImageResource(com.android.internal.R.drawable.stat_home_pressed); } }else if(key == RESV_KEY_MENU){ if(state == MotionEvent.ACTION_UP){ mMenuIcon.setImageResource(com.android.internal.R.drawable.stat_menu); }else if(state == MotionEvent.ACTION_DOWN){ mMenuIcon.setImageResource(com.android.internal.R.drawable.stat_menu_pressed); } } return 0; }   同时,我不想再在按下这些icon的时候,触发下拉动作,我也改了onInterceptTouchEvent 函数: view plain copy to clipboard print ?   @Override     public   boolean  onInterceptTouchEvent(MotionEvent event) {       if (  (event.getX() >; mHomeIcon.getRight())    &;&;  (event.getX() <; mMenuIcon.getLeft())){           return  mService.interceptTouchEvent(event)                ? true  :  super .onInterceptTouchEvent(event);       }          return   false ;   }   @Override public boolean onInterceptTouchEvent(MotionEvent event) { if( (event.getX() >; mHomeIcon.getRight()) &;&; (event.getX() <; mMenuIcon.getLeft())){ return mService.interceptTouchEvent(event) ? true : super.onInterceptTouchEvent(event); } return false; }       再编译一下,看一下结果 : ) 是不是能动了,   三,添加相应事件   1. 添加新的intent 首先是新增一条 intent , 在 framework/base/core/java/android/content/intent.java 中增加       view plain copy to clipboard print ? @SdkConstant (SdkConstantType.BROADCAST_INTENT_ACTION)   public   static   final  String ACTION_ICONKEY_CHANGED =  ";android.intent.action.ICONKEY_CHANGED"; ;   @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_ICONKEY_CHANGED = ";android.intent.action.ICONKEY_CHANGED";;      2. 发送intent    在StatusBarView.java的OnKeyEvent中,松开按键的分支else if(mResvKeyState == MotionEvent.ACTION_UP)操作中加入发送intent的动作: view plain copy to clipboard print ? Intent intent =  new  Intent(Intent.ACTION_ICONKEY_CHANGED);   intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);   intent.putExtra(";keycode"; ,   mResvKeyCode);   mService.sendIntent(intent);   Intent intent = new Intent(Intent.ACTION_ICONKEY_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); intent.putExtra(";keycode";, mResvKeyCode); mService.sendIntent(intent); 这个intent是只有注册的接收者才能接收。 这里,我们是通过StatusBarService来发送这个intent的。 在StatusBarService.java中新增一个方法: view plain copy to clipboard print ? void  sendIntent(Intent intent)   {       mContext.sendBroadcast(intent);   }   void sendIntent(Intent intent) { mContext.sendBroadcast(intent); } 3.接收并处理intent 这个就要修改StatusBarPolicy.java了 首先,在构造函数中加入Intent的filter,注册号这个intent的receiver。   filter.addAction(Intent.ACTION_ICONKEY_CHANGED); 然后再private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() 加入 Intent的receiver动作; view plain copy to clipboard print ? else   if  (action.equals(Intent.ACTION_ICONKEY_CHANGED)) {   G, ";Received ACTION_ICONKEY_CHANGED"; );       updateIconKeyAction(intent);   }   else if (action.equals(Intent.ACTION_ICONKEY_CHANGED)) { Log.d(TAG, ";Received ACTION_ICONKEY_CHANGED";); updateIconKeyAction(intent); } 方法updateIconKeyAction的定义如下:   view plain copy to clipboard print ? private   final   void  updateIconKeyAction(Intent intent){       int      keycode = intent.getIntExtra( ";keycode"; , - 1 );          if (keycode != - 1 ){           long  now = SystemClock.uptimeMillis();              try  {               KeyEvent down = new  KeyEvent(now, now, KeyEvent.ACTION_DOWN, keycode,  0 );               KeyEvent up = new  KeyEvent(now, now, KeyEvent.ACTION_UP, keycode,  0 );               (IWindowManager.Stub                   .asInterface(ServiceManager.getService(";window"; )))                   .injectKeyEvent(down, false );               (IWindowManager.Stub                   .asInterface(ServiceManager.getService(";window"; )))                   .injectKeyEvent(up, false );           } catch  (RemoteException e) {               Log.i(";Input"; ,  ";DeadOjbectException"; );           }                      }   }   private final void updateIconKeyAction(Intent intent){ int keycode = intent.getIntExtra(";keycode";, -1); if(keycode != -1){ long now = SystemClock.uptimeMillis(); try { KeyEvent down = new KeyEvent(now, now, KeyEvent.ACTION_DOWN, keycode, 0); KeyEvent up = new KeyEvent(now, now, KeyEvent.ACTION_UP, keycode, 0); (IWindowManager.Stub .asInterface(ServiceManager.getService(";window";))) .injectKeyEvent(down, false); (IWindowManager.Stub .asInterface(ServiceManager.getService(";window";))) .injectKeyEvent(up, false); } catch (RemoteException e) { Log.i(";Input";, ";DeadOjbectException";); } } } 这样,基本上就完成了。 编译一下, 由于新增了一个intent,因此要先make update-api, view plain copy to clipboard print ? ~/donut$ source ./env.sh   ~/donut$ make update-api   ~/donut$ make –j8   ~/donut$ emulator –skin WVGA800   ~/donut$ source ./env.sh ~/donut$ make update-api ~/donut$ make –j8 ~/donut$ emulator –skin WVGA800 另外,如果不是做phone,也可以在StatusBarPolicy.java中将所有phone相关的处理都删 掉。
/
本文档为【在android的状态栏(statusbar)中增加menu,home和back快捷键的方法 改进】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索