首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何获取ActionBar MenuItem的当前位置?

如何获取ActionBar MenuItem的当前位置?
EN

Stack Overflow用户
提问于 2012-05-01 20:27:05
回答 4查看 13.5K关注 0票数 21

我想在应用程序的ActionBar中的MenuItem下面显示一个小小的信息标签。要正确定位它,我需要知道MenuItem的x位置。

到目前为止,谷歌没有给我带来任何有用的结果。

这有可能吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-07-16 03:20:03

我终于找到了答案!这是有点老生常谈,但不是太多。唯一的缺点是:

  1. 您必须用您自己的View替换MenuItem%s。ImageView非常类似于标准的,但它缺少像长按查看工具提示这样的功能,可能还有其他功能。

  1. 我没怎么测试过。

好的,这就是我们怎么做的。将ActivityonCreateOptionsMenu()更改为如下所示:

代码语言:javascript
复制
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视图并重新绘制它:

代码语言:javascript
复制
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坐标。如下所示:

代码语言:javascript
复制
@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 ),你会发现它甚至更离谱。它们基本上使用由正在使用的布局确定的绝对屏幕位置。

希望这对人们有帮助!

票数 14
EN

Stack Overflow用户

发布于 2012-11-09 08:14:27

我发现了另一种在操作栏按钮上获得钩子的方法,这可能比公认的解决方案简单一点。您可以简单地使用菜单项的id调用findViewById

现在最难的部分是,当你调用的时候?在onCreateonResume中,这还为时过早。一种方法是使用窗口的ViewTreeObserver

代码语言:javascript
复制
    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的项目上测试的,所以它有可能不能与“真正的”操作栏一起工作。

票数 34
EN

Stack Overflow用户

发布于 2015-05-13 21:49:59

只需像处理普通view..like一样处理菜单项:

代码语言:javascript
复制
    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,我猜它应该是类似的工作方式。

票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/10397613

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档