How to add virtual keys on status bar?
There are 6 .png for touch up and touch down of 3 buttons Put 72 dpi and 48 dpi which can be found in Google native source code into frameworks/base/core/res/res/drawable-hdpi frameworks/base/core/res/res/drawable-mdpi respectively (P.S. it has xhdpi for supporting tablet device in Gingerbread) (in Gingerbread the directory has been changed to frameworks/base/packages/SystemUI/res/... ) and add 3 ImageView in frameworks/base/core/res/res/layout/status_bar.xml status_search, status_back, and status_menu <ImageView android:id="@+id/status_search" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="top" android:paddingTop="1dip" android:src="@drawable/search"/> <ImageView android:id="@+id/status_back" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="top" android:paddingTop="1dip" android:src="@drawable/back"/> <ImageView android:id="@+id/status_menu" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="top" android:paddingTop="1dip" android:src="@@drawable/menu"/> in frameworks/base/core/res/res/value/dimens.xml you can simply change the height of status bar by assigning <!-- Height of the status bar --> <dimen name="status_bar_height">34dip</dimen> in frameworks/base/services/java/com/android/server/status/StatusBarView.java (in Gingerbread the directory has been changed to frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/... ) add //ImageView for virtual key ImageView mSearchIcon; ImageView mBackIcon; ImageView mMenuIcon; //KeyEevent set public static final int RESV_KEY_SEARCH = KeyEvent.KEYCODE_SEARCH; public static final int RESV_KEY_BACK = KeyEvent.KEYCODE_BACK; public static final int RESV_KEY_MENU = KeyEvent.KEYCODE_MENU; //Handle touch event int mResvKeyState = -1; int mResvKeyCode = -1; in protected void onFinishInflate() {} add //ImageView for virtual key mSearchIcon = (ImageView)findViewById(R.id.status_search); mBackIcon = (ImageView)findViewById(R.id.status_back); mMenuIcon = (ImageView)findViewById(R.id.status_menu); in public boolean onTouchEvent(MotionEvent event) {} add //Added if(mResvKeyState == -1){ switch(getResvKeyArea(event)){ case RESV_KEY_SEARCH: 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); } break; } } else{ mResvKeyState = event.getAction(); if(mResvKeyState == MotionEvent.ACTION_MOVE){ if(mResvKeyCode != getResvKeyArea(event)){ updateResvKeyIcon(MotionEvent.ACTION_UP, mResvKeyCode); mResvKeyCode = -1; mResvKeyState = -1; } } else if (mResvKeyState == MotionEvent.ACTION_UP){ updateResvKeyIcon(mResvKeyState, mResvKeyCode); Intent intent = new Intent(Intent.ACTION_ICONKEY_CHANGED); intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); intent.putExtra("keycode", mResvKeyCode); mService.sendIntent(intent); mResvKeyCode = -1; mResvKeyState = -1; } else{ Slog.d(TAG, "error"); } Add 2 private functions //Private methods private int getResvKeyArea(MotionEvent event){ if((event.getX() >= mSearchIcon.getLeft() && event.getX() <= mSearchIcon.getRight()) && (event.getY() <= this.getHeight())){ return RESV_KEY_SEARCH; } else if((event.getX() >= mBackIcon.getLeft() && event.getX() <= mBackIcon.getRight()) && (event.getY() <= this.getHeight())){ return RESV_KEY_BACK; } else if((event.getX() >= mMenuIcon.getLeft() && event.getX() <= mMenuIcon.getRight()) && (event.getY() <= this.getHeight())){ return RESV_KEY_MENU; } else return -1; } //Private methods added private int updateResvKeyIcon(int state, int key){ if(key == RESV_KEY_SEARCH){ if(state == MotionEvent.ACTION_UP){ mSearchIcon.setImageResource(com.android.internal.R.drawable.search); } else if(state == MotionEvent.ACTION_DOWN){ mSearchIcon.setImageResource(com.android.internal.R.drawable.search_pressed); } } else if(key == RESV_KEY_BACK){ if(state == MotionEvent.ACTION_UP){ mBackIcon.setImageResource(com.android.internal.R.drawable.back); } else if(state == MotionEvent.ACTION_DOWN){ mBackIcon.setImageResource(com.android.internal.R.drawable.back_pressed); } } else if(key == RESV_KEY_MENU){ if(state == MotionEvent.ACTION_UP){ mMenuIcon.setImageResource(com.android.internal.R.drawable.menu); } else if(state == MotionEvent.ACTION_DOWN){ mMenuIcon.setImageResource(com.android.internal.R.drawable.menu_pressed); } } return 0; } Change public boolean onInterceptTouchEvent(MotionEvent event) {} to @Override public boolean onInterceptTouchEvent(MotionEvent event) { if(event.getX() < mSearchIcon.getLeft()){ return mService.interceptTouchEvent(event) ? true : super.onInterceptTouchEvent(event); } return false; } in frameworks/base/core/java/android/content/intent.java add our new intent @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_ICONKEY_CHANGED = "android.intent.action.ICONKEY_CHANGED"; in frameworks/base/services/java/com/android/server/status/StatusBarService.java add //function added void sendIntent(Intent intent){ mContext.sendBroadcast(intent); } in frameworks/base/services/java/com/android/server/status/StatusBaPolicy.java find the field where to add registration for intents and add //Action added filter.addAction(Intent.ACTION_ICONKEY_CHANGED); mContext.registerReceiver(mIntentReceiver, filter, null, mHandler); in private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {} add //added else if (action.equals(Intent.ACTION_ICONKEY_CHANGED)) { updateIconKeyAction(intent); } add our private function //added private final void updateIconKeyAction(Intent intent){ int keycode = intent.getIntExtra("keycode", -1); if(keycode != -1){ long now = SystemClock.suptimeMillis(); 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) { } } } Done Remember to make update-api to update frameworks/base/api/current.xml and see if our intent is already added <field name="ACTION_ICONKEY_CHANGED" type="java.lang.String" transient="false" volatile="false" value=""android.intent.action.ICONKEY_CHANGED"" static="true" final="true" deprecated="not deprecated" visibility="public" > Result
|