我想在应用程序的ActionBar
中的MenuItem
下面显示一个小小的信息标签。要正确定位它,我需要知道MenuItem
的x位置。
到目前为止,谷歌没有给我带来任何有用的结果。
这有可能吗?
发布于 2012-07-16 03:20:03
我终于找到了答案!这是有点老生常谈,但不是太多。唯一的缺点是:
View
替换MenuItem
%s。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;
}
然后有一个函数可以用按钮的位置更新有帮助的instructions视图并重新绘制它:
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
。
顺便说一句,如果你看一下谷歌为启动程序实现的类似实现的源代码(出于某种原因,他们将说明屏幕称为Cling
),你会发现它甚至更离谱。它们基本上使用由正在使用的布局确定的绝对屏幕位置。
希望这对人们有帮助!
发布于 2012-11-09 08:14:27
我发现了另一种在操作栏按钮上获得钩子的方法,这可能比公认的解决方案简单一点。您可以简单地使用菜单项的id调用findViewById
!
现在最难的部分是,当你调用的时候?在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的项目上测试的,所以它有可能不能与“真正的”操作栏一起工作。
发布于 2015-05-13 21:49:59
只需像处理普通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);
}
注意:我已经使用ToolBar配置了我的activity进行了测试,而不是直接作为ActionBar...but,我猜它应该是类似的工作方式。
https://stackoverflow.com/questions/10397613
复制相似问题