MenuItem
アプリの の下に小さな情報ラベルを表示したいと思いActionBar
ます。これを正しく配置するには、 a の x 位置を知る必要がありMenuItem
ます。
これまでのところ、Google は有用な結果をもたらしませんでした。
それは可能ですか?
MenuItem
アプリの の下に小さな情報ラベルを表示したいと思いActionBar
ます。これを正しく配置するには、 a の x 位置を知る必要がありMenuItem
ます。
これまでのところ、Google は有用な結果をもたらしませんでした。
それは可能ですか?
アクションバーボタンにフックを付ける別の方法を見つけました。これは、受け入れられている解決策よりも少し簡単かもしれません。findViewById
メニュー項目の id を使用して を呼び出すだけです。
ここで難しいのは、いつこれを呼び出すことができるかということです。onCreate
とではonResume
、早すぎます。これを行う 1 つの方法ViewTreeObserver
は、ウィンドウのを使用することです。
final ViewTreeObserver viewTreeObserver = getWindow().getDecorView().getViewTreeObserver();
viewTreeObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
View menuButton = findViewById(R.id.menu_refresh);
// This could be called when the button is not there yet, so we must test for null
if (menuButton != null) {
// Found it! Do what you need with the button
int[] location = new int[2];
menuButton.getLocationInWindow(location);
Log.d(TAG, "x=" + location[0] + " y=" + location[1]);
// Now you can get rid of this listener
viewTreeObserver.removeGlobalOnLayoutListener(this);
}
}
});
これが入りonCreate
ます。
注: これは ActionBarSherlock を使用するプロジェクトでテストされているため、「実際の」アクション バーでは機能しない可能性があります。
私はついにこれに対する答えを見つけました!少しハッキーですが、それほど多くはありません。唯一の欠点は次のとおりです。
MenuItem
s を独自のに置き換える必要がありますView
。は標準のImageView
ものとかなり似ていますが、長押ししてツールチップを表示するなどの機能が欠けています。
私はそれをあまりテストしていません。
わかりました、これが私たちのやり方です。Activity
を次のonCreateOptionsMenu()
ように変更します。
View mAddListingButton;
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
getMenuInflater().inflate(R.menu.activity_main, menu);
// Find the menu item we are interested in.
MenuItem it = menu.findItem(R.id.item_new_listing);
// Create a new view to replace the standard one.
// It would be nice if we could just *get* the standard one
// but unfortunately it.getActionView() returns null.
// actionButtonStyle makes the 'pressed' state work.
ImageView button = new ImageView(this, null, android.R.attr.actionButtonStyle);
button.setImageResource(R.drawable.ic_action_add_listing);
// The onClick attributes in the menu resource no longer work (I assume since
// we passed null as the attribute list when creating this button.
button.setOnClickListener(this);
// Ok, now listen for when layouting is finished and the button is in position.
button.addOnLayoutChangeListener(new OnLayoutChangeListener() {
@Override
public void onLayoutChange(View v, int left, int top, int right, int bottom,
int oldLeft, int oldTop, int oldRight, int oldBottom)
{
// Apparently this can be called before layout is finished, so ignore it.
// Remember also that it might never be called with sane values, for example
// if your action button is pushed into the "more" menu thing.
if (left == 0 && top == 0 && right == 0 && bottom == 0)
return;
// This is the only way to get the absolute position on the screen.
// The parameters passed to this function are relative to the containing View
// and v.getX/Y() return 0.
int[] location = new int[2];
v.getLocationOnScreen(location);
// Ok, now we know the centre location of the button in screen coordinates!
informButtonLocation(location[0] + (right-left)/2, location[1] + (bottom-top)/2);
}
});
it.setActionView(button);
mAddListingButton = it.getActionView();
return true;
}
次に、ボタンの位置を使用して役立つ指示ビューを更新し、再描画する関数があります。
private void informButtonLocation(int cx, int cy)
{
MyHelpView v = (MyHelpView)findViewById(R.id.instructions);
v.setText("Click this button.");
v.setTarget(cx, cy);
}
最後に、ボタンの (近くに) 矢印を描画する派手なカスタム ビューを作成します。メソッドでは、同じ関数を使用onDraw
して画面座標を座標に戻すことができます。このようなもの:Canvas
getLocationOnScreen
@Override
public void onDraw(Canvas canvas)
{
int[] location = new int[2];
getLocationOnScreen(location);
canvas.drawColor(Color.WHITE);
mPaint.setColor(Color.BLACK);
mPaint.setTextSize(40);
mPaint.setAntiAlias(true);
mPaint.setTextAlign(Align.CENTER);
canvas.drawText(mText, getWidth()/2, getHeight()/2, mPaint);
// Crappy line that isn't positioned right at all and has no arrowhead.
if (mTargetX != -1 && mTargetY != -1)
canvas.drawLine(getWidth()/2, getHeight()/2,
mTargetX - location[0], mTargetY - location[1], mPaint);
}
(ただし、明らかに、ターゲットの場所をキャンバスのサイズにクリップする必要があります)。画面全体にビューを重ねる Google と同じ方法を使用する場合は、心配する必要はありませんが、より煩わしくなります。Google の方法は、(驚くべきことに) プライベート API をまったく使用していません。Cling.java
Launcher2 コードをチェックアウトします。
ちなみに、これをランチャーに実装した Google の同様の実装 (Cling
何らかの理由で指示画面を a と呼んでいます) のソースを見ると、さらにハックであることがわかります。基本的に、どのレイアウトが使用されているかによって決定される絶対画面位置を使用します。
これが人々を助けることを願っています!
メニュー項目を通常のビューとして処理するだけです..次のように:
View myActionView = findViewById(R.id.my_menu_item_id);
if (myActionView != null) {
int[] location = new int[2];
myActionView.getLocationOnScreen(location);
int x = location[0];
int y = location[1];
Log.d(TAG, "menu item location --> " + x + "," + y);
}
注: ActionBar として直接ではなく、ToolBar を使用して構成されたアクティビティでテストしましたが、同様に動作するはずです。
この回答は現在古くなっています。上記の受け入れられた回答を探してください
(現時点では) メニュー項目の x/y 値を計算する方法がないことがわかりました。メニュー項目は、ユーザーがメニュー ボタンを押すまで画面から非表示にすることもできます。Android 3.0 以降では、アプリの にメニューを実装するオプションがありますActionBar
。アクションバーに多くのメニューアイテムを追加できます。バーにアイテムを配置する場所がなくなった場合、アクションバーに配置できなかったすべてのメニューアイテムを含む「オーバーフロー」ボタンが作成されます。スペースが不足している、またはプログラマーが明示的にメニュー項目をオーバーフロー メニューに表示するように設定したためです。
このすべての動作が、メニュー項目に取得 (または設定) できる x/y 位置がない理由であると考えられます。
この問題を最終的にどのように解決したかは、Paint.measureText()
関数を使用してアクション バー内の各メニュー項目の幅を決定し、それを使用して、ラベルがあるべき画面の右側からのオフセットを計算することです。
これは回避策ですが、誰かが私と同じ問題を抱えている場合は、これでうまくいくことを知っておいてください。オブジェクトに適切な font-size を設定することを忘れないでPaint
ください。 そうしないと、テキストの長さを測定するときに、メニュー項目の font-size とは異なる font-size を使用してテキストの幅が計算される可能性が高くなります。