您的位置:首页 > 移动开发 > Android开发

[Android 問題] How to Add Virtual Keys on Status Bar?

2011-01-25 16:50 676 查看
How to add virtual keys on status bar?

(for the version before Froyo)

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



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: