长按ActionBar中的Menu菜单,会弹出提示框(实际上是一个Toast),如下图所示。
现在来看看它的实现方式:
其中的Menu选项,实为ActionMenuItemView类(frameworks/base/core/java/com/android/internal/view/menu/ActionMenuItemView)。
ActionMenuItemView.onLongClick() 代码如下。
@Override
public boolean onLongClick(View v) {
if (hasText()) {
// Don't show the cheat sheet for items that already show text.
return false;
}
final int[] screenPos = new int[2];
final Rect displayFrame = new Rect();
getLocationOnScreen(screenPos);
getWindowVisibleDisplayFrame(displayFrame);
final Context context = getContext();
final int width = getWidth();
final int height = getHeight();
final int midy = screenPos[1] + height / 2;
final int screenWidth = context.getResources().getDisplayMetrics().widthPixels;
Toast cheatSheet = Toast.makeText(context, mItemData.getTitle(), Toast.LENGTH_SHORT);
if (midy < displayFrame.height()) {
// Show along the top; follow action buttons
cheatSheet.setGravity(Gravity.TOP | Gravity.RIGHT,
screenWidth - screenPos[0] - width / 2, height);
} else {
// Show along the bottom center
cheatSheet.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, height);
}
cheatSheet.show();
return true;
}
代码分析:
“hasText()”,判断该MenuItem是否已显示了文字。如果是,则不显示提示框;如果否,代码继续往下;
“getLocationOnScreen(int[] location)”,获取该MenuItem在整个屏幕内的绝对坐标,注意这个值是要从屏幕顶端算起,也就是包括了通知栏的高度。与这个方法类似的“getLocationInWindow(int[] location)”,它获取的是在当前窗口内的绝对坐标;
“getWindowVisibleDisplayFrame(Rect outRect)”,获取当前窗口的显示区域;
接下去的代码就是创建一个Toast,并设置它的Gravity及偏移量。
这段代码可以很容易移植到自己的控件中,以实现类似的长按反馈。