Androidのステータスバーにmenu,home,backショートカットキーを追加する方法
説明しなければならないのは、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に3つのimage viewを追加しました
このようにするメリットは簡単です.同時に、右端がホームボタンであり、左端がbackボタンであり、本来の制約を受けないことを保証します.これでstatus barにこれらのボタンが表示されます.アイコンの位置は、paddingRight、paddingLeft、paddingTopの値を変更することで最適な視覚効果を得ることができます.
2.status barの高さを変更します.
status barにいくつかのボタンを追加する以上、もちろんタッチ操作を使いたいのですが、androidが持参したstatus barの高さが小さすぎて適用されません.7インチスクリーンの場合、50 pixelの高さはあまり差がないはずです.高さを修正するのは簡単で、私が回ったshinning mmの博文のようです.frameworks/base/core/res/res/values/dimensを変更します.xmlのstatus_bar_Height属性50 dipもちろんtitleの高さを変更するとFrameworks/base/core/res/res/values/themesを変更することができる.xmlのWindow attributesのwindowTitleSize値ですが、必要ないと思いますが、変更するとかえって面白くありません:)
コンパイルを実行します.
ステータスバーが変わったかどうか見てみましょうか?
2ボタンにダイナミックエフェクトを追加する
ダイナミックエフェクトを追加すると、hilightをタッチして押したり、放したり、外したりして回復する動作です.これはframeworks/base/services/java/com/android/server/status/statusBarViewを変更します.JAvaが実現しました.
1.statusbarに新しく追加されたiconのhandlerを取得します.
クラスに新たに3人のメンバーを追加します(import android.widget.ImageView;):
同時に3つの定数を増やして、これらのiconに対応するキー値を表します(これはimport android.view.KeyEventが必要です;)
onFinishInflate()で、実際のオブジェクトを取得します.
この3つのオブジェクトは私たちがstatusにいることです.bar.xmlに追加されました.
2.タッチ処理を追加します.まず、そのアイコンが押されたと判断すべきで、これはStatusBarViewにあります.JavaのonTouchEventで判断します.ここで、私は小さなボタン状態をして、押したり、弾いたり、移動したりする動作を簡単に処理しました.まず、2つのステータスメンバーを追加します.
これで私のonTouchEventはこうなりました.
ここで使用する2つのprivateメソッドは、以下のように簡単に実現されます.
また、これらのiconを押すときにドロップダウン動作をトリガーしたくないので、onInterceptTouchEvent関数も変更しました.
もう一度コンパイルして、結果を見てみましょう:)動くことができますか?三、対応するイベントを追加する
1.新しいintentを追加するには、まずframework/base/core/java/android/content/intentにintentを追加します.JAvaで追加
2.intentの送信
StatusBarViewでJAvaのOnKeyEventでは、キーを離すブランチelse if(mResvKeyState==MotionEvent.ACTION_UP)操作にintentを送信する動作を加える.
このintentは登録された受信者のみが受信できます.ここでは、このintentをStatusBarServiceで送信します.
StatusBarServicesでJAvaには、次の方法が追加されました.
3.intentこれを受け取って処理するにはStatusBarPolicyを修正する.JAva
まず,コンストラクション関数にIntentのfilter,登録番号というintentのreceiverを加える.
filter.addAction(Intent.ACTION_ICONKEY_CHANGED);
次にprivate BroadcastReceiver mIntentReceiver=new BroadcastReceiver()をIntentのreceiver動作に追加します.
メソッドupdateIconKeyActionの定義は次のとおりです.
これで、ほぼ完成です.
コンパイルすると、intentが追加されたので、まずmake update-api、
またphoneでなければStatusBarPolicy.JAvaではすべてのphoneに関する処理を削除します.
テキストリンク:http://disanji.net/2011/04/13/android-statusbar-menu-home-back-shortkey/
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に3つのimage viewを追加しました
<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>
このようにするメリットは簡単です.同時に、右端がホームボタンであり、左端がbackボタンであり、本来の制約を受けないことを保証します.これでstatus barにこれらのボタンが表示されます.アイコンの位置は、paddingRight、paddingLeft、paddingTopの値を変更することで最適な視覚効果を得ることができます.
2.status barの高さを変更します.
status barにいくつかのボタンを追加する以上、もちろんタッチ操作を使いたいのですが、androidが持参したstatus barの高さが小さすぎて適用されません.7インチスクリーンの場合、50 pixelの高さはあまり差がないはずです.高さを修正するのは簡単で、私が回ったshinning mmの博文のようです.frameworks/base/core/res/res/values/dimensを変更します.xmlのstatus_bar_Height属性50 dipもちろんtitleの高さを変更するとFrameworks/base/core/res/res/values/themesを変更することができる.xmlのWindow attributesのwindowTitleSize値ですが、必要ないと思いますが、変更するとかえって面白くありません:)
コンパイルを実行します.
~/donut$ source ./env.sh
~/donut$ make –j8
~/donut$ emulator –skin WVGA800
ステータスバーが変わったかどうか見てみましょうか?
2ボタンにダイナミックエフェクトを追加する
ダイナミックエフェクトを追加すると、hilightをタッチして押したり、放したり、外したりして回復する動作です.これはframeworks/base/services/java/com/android/server/status/statusBarViewを変更します.JAvaが実現しました.
1.statusbarに新しく追加されたiconのhandlerを取得します.
クラスに新たに3人のメンバーを追加します(import android.widget.ImageView;):
ImageView mHomeIcon;
ImageView mBackIcon;
ImageView mMenuIcon;
同時に3つの定数を増やして、これらのiconに対応するキー値を表します(これはimport android.view.KeyEventが必要です;)
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()で、実際のオブジェクトを取得します.
mHomeIcon = (ImageView)findViewById(R.id.status_home);
mBackIcon = (ImageView)findViewById(R.id.status_back);
mMenuIcon = (ImageView)findViewById(R.id.status_menu);
この3つのオブジェクトは私たちがstatusにいることです.bar.xmlに追加されました.
2.タッチ処理を追加します.まず、そのアイコンが押されたと判断すべきで、これはStatusBarViewにあります.JavaのonTouchEventで判断します.ここで、私は小さなボタン状態をして、押したり、弾いたり、移動したりする動作を簡単に処理しました.まず、2つのステータスメンバーを追加します.
int mResvKeyState = -1; // , -1 。
int mResvKeyCode = -1; // ,-1 。
これで私のonTouchEventはこうなりました.
@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;
}
ここで使用する2つのprivateメソッドは、以下のように簡単に実現されます.
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関数も変更しました.
@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を追加するには、まずframework/base/core/java/android/content/intentにintentを追加します.JAvaで追加
@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を送信する動作を加える.
Intent intent = new Intent(Intent.ACTION_ICONKEY_CHANGED);
intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
intent.putExtra("keycode", mResvKeyCode);
mService.sendIntent(intent);
このintentは登録された受信者のみが受信できます.ここでは、このintentをStatusBarServiceで送信します.
StatusBarServicesでJAvaには、次の方法が追加されました.
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動作に追加します.
else if (action.equals(Intent.ACTION_ICONKEY_CHANGED)) {
Log.d(TAG, "Received ACTION_ICONKEY_CHANGED");
updateIconKeyAction(intent);
}
メソッドupdateIconKeyActionの定義は次のとおりです.
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、
~/donut$ source ./env.sh
~/donut$ make update-api
~/donut$ make –j8
~/donut$ emulator –skin WVGA800
またphoneでなければStatusBarPolicy.JAvaではすべてのphoneに関する処理を削除します.
テキストリンク:http://disanji.net/2011/04/13/android-statusbar-menu-home-back-shortkey/