アプリのActionBar
のMenuItem
の下に小さな情報ラベルを表示したいのですが、 これを正しく配置するには、MenuItem
のx位置を知る必要があります。ActionBar MenuItemの現在の位置を取得するにはどうすればよいですか?
Googleは今まで私に有用な結果をもたらしていませんでした。
それは可能ですか?
アプリのActionBar
のMenuItem
の下に小さな情報ラベルを表示したいのですが、 これを正しく配置するには、MenuItem
のx位置を知る必要があります。ActionBar MenuItemの現在の位置を取得するにはどうすればよいですか?
Googleは今まで私に有用な結果をもたらしていませんでした。
それは可能ですか?
私はついにこれに答えました!ちょっとハッキリですが、それほど多くはありません。唯一の欠点は次のとおりです。
MenuItem
を自分のView
に置き換える必要があります。 ImageView
は標準的なものとかなり似ていますが、ツールチップや他のものを見るために長時間押すような機能は欠けています。[OK]を次に示します。
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;
}
そして、あなたはあなたの役に立つ命令はボタンの位置を表示し、それを再描画更新機能を持っている:このような何かにあなたの
Activity
の
onCreateOptionsMenu()
を変更
private void informButtonLocation(int cx, int cy)
{
MyHelpView v = (MyHelpView)findViewById(R.id.instructions);
v.setText("Click this button.");
v.setTarget(cx, cy);
}
は、最後にあなたを作りますボタンの近くに矢印を描く派手なシャーマンのカスタムビュー。 onDraw
メソッドでは、同じgetLocationOnScreen
関数を使用して、画面座標をCanvas
座標に戻すことができます。このようなもの:
@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は使用していません(驚くほど)。 Launcher2コードでCling.java
をチェックしてください。
ちなみに、ランチャー用のGoogleの同様の実装のソース(何らかの理由で指示画面Cling
と呼んでいます)を見ると、それはさらにハッキーです。基本的には、どのレイアウトを使用しているかによって決まる絶対的なスクリーン位置を使用します。
これは人々に役立つことを願っています!
この回答は
上記受け入れ答えを探し、私は(現時点では)メニューアイテムのx/yの値を考え出すの方法がないことが判明、今時代遅れです。ユーザーがメニューボタンを押すまでは、メニュー項目は画面から隠すこともできます。 Android 3.0以降では、アプリのActionBar
にメニューを実装するオプションがあります。アクションバーに多くのメニューアイテムを追加することができます。バーにアイテムを配置する場所がなくなると、単にアクションバーに配置できなかったすべてのメニューアイテムを含む「オーバーフロー」ボタンが作成されます。またはプログラマーがオーバーフローメニューに表示するようにメニュー項目を明示的に設定したためです。
このような現象は、おそらくメニュー項目のx/y位置が検索(または設定)できないためです。
どのようにこの問題を解決したのですか?Paint.measureText()
関数を使用して、アクションバーの各メニュー項目の幅を決定し、それを使用してラベルが表示される画面の右側からのオフセットを計算します。
これは回避策ですが、誰かが私と同じ問題を抱えている場合は、うまく動作することをご存知でしょうか。 Paint
オブジェクトに適切なフォントサイズを設定することを忘れないでください。そうでない場合は、テキストの長さを測定するときには、おそらくメニュー項目のfont-sizeとは異なるフォントサイズを使用してテキスト幅を計算します。
私は、アクションバーのボタンにフックをつける別の方法を見つけました。これは、受け入れられた解決策より少し単純かもしれません。 findViewById
は、メニュー項目のIDで簡単に呼び出すことができます。
ハード部分がの場合と呼びますか? onCreate
とonResume
では、早すぎます。さて、これを行うための一つの方法は、ウィンドウの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を使用してプロジェクトでテストされているため、「実際の」アクションバーでは機能しない可能性があります。
ちょうどこのview..like通常通りにメニュー項目を扱う:
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);
}
注:私は私の活動でテストしてみたがアクションバーとして直接、ツールバーを使用して設定していない...しかし、私同じように動作するはずです。
これをonOptionsItemSelected内で呼び出すこともできます。 – Simon
これは実際に問題なく動作します。私は既にそれが役に立っている時間がすでにありましたが(私はすでに自分のソリューションを使用していました、下記を参照)、アプリケーションを変更することは今の選択肢ではありません。しかし、将来的に他の人に役立つことを願っています!素晴らしい答え! – Pieter888
addOnLayoutChangeListenerはHoneycombからのみサポートされています。それは古いAPIでは動作しません。 –
私は今座標を持っていますが、断片の上に描画する方法は? – Skynet