ListView的长按菜单___源码分析

ListView的长按菜单___源码分析

Android的listview可以长按弹出来一个菜单。
今天就跟了下代码大概看了下弹出菜单的流程。
我们实现一个菜单长按步骤通常如下:

1.弹出菜单的生成
如果控制listview长按应该生成什么样的菜单。
a、生成一个OnCreateContextMenuListener的接口对象
该接口定义如下:在view.java中
public interface OnCreateContextMenuListener {  
    /** 
     * Called when the context menu for this view is being built. It is not 
     * safe to hold onto the menu after this method returns. 
     * 
     * @param menu The context menu that is being built 
     * @param v The view for which the context menu is being built 
     * @param menuInfo Extra information about the item for which the 
     *            context menu should be shown. This information will vary 
     *            depending on the class of v. 
     */  
    void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo);  
} 


b、实现该接口的onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo)函数
在这里,根据menuInfo,通常先转换为AdapterContextMenuInfo,定义如下,在adapterview.java中定义
public static class AdapterContextMenuInfo implements ContextMenu.ContextMenuInfo { 
 
    public AdapterContextMenuInfo(View targetView, int position, long id) {  
        this.targetView = targetView;  
        this.position = position;  
        this.id = id;  
    }  
 
    /** 
     * The child view for which the context menu is being displayed. This 
     * will be one of the children of this AdapterView. 
     */  
    public View targetView;  
 
    /** 
     * The position in the adapter for which the context menu is being 
     * displayed. 
     */  
    public int position;  
 
    /** 
     * The row id of the item for which the context menu is being displayed. 
     */  
    public long id;  
}


通过获取MenuItem 的postion进而获取该listitem的信息,进而来决定加入什么样的菜单。

c、将该接口对象设置为listview的listener
setOnCreateContextMenuListener(l)



2、菜单选择事件的响应
实现该listview的单击响应事件
public boolean onContextItemSelected(MenuItem item) {}

根据不同的MenuItem的id来进行不同的操作。

二、onCreateContextMenu的调用
那么OnCreateContextMenuListener的onCreateContextMenu是在什么时候调用的呢
是在view.java中createContextMenu函数中调用。
view.createContextMenu是在ContextMenubuilder的show函数调用
而ContextMenubuilder的show函数分别在
PhoneWindow和MidWindow的showContextMenuForChild调用。
再往下今天就没再跟下去了。

三、onCreateContextMenu的生成
在onCreateContextMenu(menu, this, menuInfo)时,传入一个MenuInfo,我们就根据这个MenuInfo来创建响应的菜单。

那这个MenuInfo是怎样生成的呢?
1、首先在View中createContextMenu,调用ContextMenuInfo menuInfo = getContextMenuInfo();

但是getContextMenuInfo()就是返回一个空,得不得我们的数据。

所以,一个view要想能够生成自己的MenuInfo,必须要重新getContextMenuInfo这个函数。
2、在上面的步骤中,我们没有涉及到该函数的重写 ,是因为ListView的父类中,已经重写了改函数 。如下
@Override
protected ContextMenuInfo getContextMenuInfo() {  
    return mContextMenuInfo;  
} 

而这个成员变量的赋值如下:
private boolean performLongPress(final View child,final int longPressPosition, final long longPressId) {  
    boolean handled = false;  
    if (mOnItemLongClickListener != null) {  
        handled = mOnItemLongClickListener.onItemLongClick(AbsListView.this, child,  
                longPressPosition, longPressId);  
    }  
 
    if (!handled) {  
        mContextMenuInfo = createContextMenuInfo(child, longPressPosition, longPressId);  
        handled = super.showContextMenuForChild(AbsListView.this);  
    } 
 
    if (handled) {  
        performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);  
    } 
 
    return handled;  
}
  
ContextMenuInfo createContextMenuInfo(View view, int position, long id) {  
    return new AdapterContextMenuInfo(view, position, id);  
} 
 
ContextMenuInfo createContextMenuInfo(View view, int position, long id) {  
    return new AdapterContextMenuInfo(view, position, id);  
}


就是我们在构造菜单时候所用到的ContextMenuInfo.

如果我们要给其它自己定义的View,响应长按菜单。这时候我们就需要重写该View的getContextMenuInfo()。

根据View当前状态生成不同的ContextMenuInfo,进而决定应该弹出什么样的菜单。


你可能感兴趣的:(ListView)