Android中实现菜单的方式有:
- Menu
- PopWindow
- ContextMenu
这里来试着说一说ContextMenu的用法。
先来看效果图:
实现步骤:
为指定的View注册上下文菜单
registerForContextMenu
重写
onCreateContextMenu
onContextItemSelected
这两个方法。下面是详细的示例代码:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = (TextView) findViewById(R.id.main_tv);
registerForContextMenu(textView);
Button btn = (Button) findViewById(R.id.main_btn);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "btn is clicked", Toast.LENGTH_SHORT).show();
}
});
registerForContextMenu(btn);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
switch (v.getId()) {
case R.id.main_tv:
menu.add(0, 0, 0, "position0");
menu.add(0, 1, 0, "position1");
break;
case R.id.main_btn:
menu.add(0, 2, 0, "position2");
menu.add(0, 3, 0, "position3");
break;
default:
break;
}
super.onCreateContextMenu(menu, v, menuInfo);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
Toast.makeText(this, item.getItemId() + "", Toast.LENGTH_SHORT).show();
return super.onContextItemSelected(item);
}
我们可以看到,可以同时为多个view注册上下文菜单,并且可同时为button设置onClickListener
和上下文菜单。到这我产生了一个疑问,我们都知道onClickLisener
是在view的onTouchEvent
方法里的performClick
中被调用的,那上下文菜单是在哪被调用的呢?接下来,只能去看源码。
我们从入口一步一步的找:
public void registerForContextMenu(View view) {//入口
view.setOnCreateContextMenuListener(this);
}
//view的setOnCreateContextMenuListener方法
public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
if (!isLongClickable()) {//If this view is not long clickable, it becomes long clickable
setLongClickable(true);
}
getListenerInfo().mOnCreateContextMenuListener = l;//getListenerInfor()会得到一个ListenerInfo类,它是View的静态内部类,里面持有各种监听器,比如onClickListener、OnFocusChangeListener等
}
可以看到,调用registerForContextMenu
只是给view里的变量赋了个值。在哪调用了mOnContextClickListener
?接着找吧。
//顺藤摸瓜,顺着mOnContextClickListener找到了performContextClick
public boolean performContextClick() {
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_CONTEXT_CLICKED);
boolean handled = false;
ListenerInfo li = mListenerInfo;
if (li != null && li.mOnContextClickListener != null) {
handled = li.mOnContextClickListener.onContextClick(View.this);//具体调用的地方
}
if (handled) {
performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK);
}
return handled;
}
//接着找发现,performAccessibilityActionInternal调用了performContextClick,而performAccessibilityAction调用了performAccessibilityActionInternal方法,所以具体的调用流程是performAccessibilityAction-》performAccessibilityActionInternal-》performContextClick,详细代码太多了,就不贴出来了。