Android Toolbar overflow menu view id

2020-04-01 09:35发布

What I am trying to do is showing a PopupWindow pointing to the overflow icon (the three dots) on the Toolbar. So I need to get a reference to the View object with the id of the icon. But what is the id?

The PopupWindow is used to tell the users that there are new entries added to the overflow menu. And suggest users to check it out.

标签: android
5条回答
家丑人穷心不美
2楼-- · 2020-04-01 10:10

The overflow menu item doesn't have a resource id. I found the overflow view by traversing the toolbar. The debugger showed an id of -1 and the Hierarchy Viewer showed no resource-id.

Here is how I found the overflow view without a resource id:

/**
 * Get the OverflowMenuButton.
 *
 * @param activity
 *     the Activity
 * @return the OverflowMenuButton or {@code null} if it doesn't exist.
 */
public static ImageView getOverflowMenuButton(Activity activity) {
  return findOverflowMenuButton(activity, findActionBar(activity));
}

static ImageView findOverflowMenuButton(Activity activity, ViewGroup viewGroup) {
  if (viewGroup == null) {
    return null;
  }
  ImageView overflow = null;
  for (int i = 0, count = viewGroup.getChildCount(); i < count; i++) {
    View v = viewGroup.getChildAt(i);
    if (v instanceof ImageView && (v.getClass().getSimpleName().equals("OverflowMenuButton") ||
        v instanceof ActionMenuView.ActionMenuChildView)) {
      overflow = (ImageView) v;
    } else if (v instanceof ViewGroup) {
      overflow = findOverflowMenuButton(activity, (ViewGroup) v);
    }
    if (overflow != null) {
      break;
    }
  }
  return overflow;
}

static ViewGroup findActionBar(Activity activity) {
  try {
    int id = activity.getResources().getIdentifier("action_bar", "id", "android");
    ViewGroup actionBar = null;
    if (id != 0) {
      actionBar = (ViewGroup) activity.findViewById(id);
    }
    if (actionBar == null) {
      return findToolbar((ViewGroup) activity.findViewById(android.R.id.content).getRootView());
    }
  } catch (Exception e) {
    e.printStackTrace();
  }
  return null;
}

static ViewGroup findToolbar(ViewGroup viewGroup) {
  ViewGroup toolbar = null;
  for (int i = 0, len = viewGroup.getChildCount(); i < len; i++) {
    View view = viewGroup.getChildAt(i);
    if (view.getClass() == android.support.v7.widget.Toolbar.class ||
        view.getClass().getName().equals("android.widget.Toolbar")) {
      toolbar = (ViewGroup) view;
    } else if (view instanceof ViewGroup) {
      toolbar = findToolbar((ViewGroup) view);
    }
    if (toolbar != null) {
      break;
    }
  }
  return toolbar;
}

Calling getOverflowMenuButton(activity) will return null in onCreate because the overflow menu isn't laid out yet. To get the overflow menu in onCreate I did the following:

findViewById(android.R.id.content).post(new Runnable() {
  @Override public void run() {
    ImageView overflow = getOverflowMenuButton(MainActivity.this);
  }
});
查看更多
做自己的国王
3楼-- · 2020-04-01 10:12

you want to create custom DropDown menu? consider this "native" way

or use android:showAsAction="never" in your menu.xml. doc of showAsAction attribute HERE. when one of MenuItems have set never value then you will get overflow three-dot icon automatically and these MenuItems will be hidding there

also you may try to use Hierarchy Viewer to investigate this id if really needed

查看更多
Viruses.
4楼-- · 2020-04-01 10:24

I found a library called TapTarget and a function TapTarget.forToolbarOverflow(). It presents a solution: https://github.com/KeepSafe/TapTargetView/blob/master/taptargetview/src/main/java/com/getkeepsafe/taptargetview/TapTarget.java#L96

The way how it finds the overflow view is not neat but should be stable.

查看更多
太酷不给撩
5楼-- · 2020-04-01 10:26

Instead of using expensive and complicated layout traversal to find the overflow menu, I have achieved showing the PopupWindow under the overflow menu by using the Toolbar view as anchor and setting gravity to Gravity.END:

 /**
  * Sets the anchor view and shows the popup. In case of narrow display the menu items may be hidden in an overflow
  * menu, in that case anchorView may be null and the popup will be anchored to the end of the toolbar.
  */
 public void show(@Nullable View anchorView, @NonNull View toolbarView) {
     if (anchorView == null) {
         setDropDownGravity(Gravity.END);
         setAnchorView(toolbarView);
     } else {
         setAnchorView(anchorView);
     }
     show();
 }
查看更多
Evening l夕情丶
6楼-- · 2020-04-01 10:32

You probably created a menu item xml in your menu ressources to have an overflow button, so you must use the id of the overflow button item that you specified in your menu xml

查看更多
登录 后发表回答