Android 上下文菜单无法处理两个片段

Android 上下文菜单无法处理两个片段,android,android-fragments,contextmenu,long-press,Android,Android Fragments,Contextmenu,Long Press,我有两个片段A和B,它们都有一个listview,并从一个基本片段C扩展而来。实际上,A和B从C扩展了listview控件 为了实现长按功能,我在C中注册了上下文菜单 现在,当我长按fragment A或B时,上下文菜单可以按预期显示。同样,当我在片段A中时,上下文菜单也可以工作 但我们导航到片段B,长按list,从未调用onContextItemSelected方法 我是这样做的。 首先,在片段C中的ActivityCreated上注册上下文菜单 registerForContextMenu(

我有两个片段A和B,它们都有一个listview,并从一个基本片段C扩展而来。实际上,A和B从C扩展了listview控件

为了实现长按功能,我在C中注册了上下文菜单

现在,当我长按fragment A或B时,上下文菜单可以按预期显示。同样,当我在片段A中时,上下文菜单也可以工作

但我们导航到片段B,长按list,从未调用
onContextItemSelected
方法

我是这样做的。 首先,在片段C中的ActivityCreated上注册上下文菜单

registerForContextMenu(transferTasksList);
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
                                ContextMenu.ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    android.view.MenuInflater inflater = mActivity.getMenuInflater();
    inflater.inflate(R.menu.upload_task_menu, menu);

    ListView listView = (ListView)v;
    AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
    TransferTaskInfo taskInfo = (TransferTaskInfo)listView.getItemAtPosition(info.position);

    android.view.MenuItem itemCancel = menu.findItem(R.id.cancel);
    android.view.MenuItem itemRetry = menu.findItem(R.id.retry);
    android.view.MenuItem itemRemove = menu.findItem(R.id.remove);
    android.view.MenuItem itemRemoveAllCancelled = menu.findItem(R.id.remove_all_cancelled);
    android.view.MenuItem itemRemoveAllFinished = menu.findItem(R.id.remove_all_finished);

    itemCancel.setVisible(false);
    itemRetry.setVisible(false);
    itemRemove.setVisible(false);
    itemRemoveAllCancelled.setVisible(false);
    itemRemoveAllFinished.setVisible(false);

    switch (taskInfo.state) {
        case INIT:
            itemCancel.setVisible(true);
            break;
        case TRANSFERRING:
            itemCancel.setVisible(true);
            break;
        case CANCELLED:
            itemRetry.setVisible(true);
            itemRemove.setVisible(true);
            itemRemoveAllCancelled.setVisible(true);
            break;
        case FAILED:
            itemRetry.setVisible(true);
            itemRemove.setVisible(true);
            break;
        case FINISHED:
            itemRemove.setVisible(true);
            itemRemoveAllFinished.setVisible(true);
            break;
    }
}
@Override
    public boolean onContextItemSelected(android.view.MenuItem item) {
        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();

        TransferService txService = mActivity.getTransferService();

        if (txService == null) {
            return false;
        }

        ListView listView = transferTasksList;
        TransferTaskInfo taskInfo = (TransferTaskInfo)listView.getItemAtPosition(info.position);
        TransferManager.TaskState state = taskInfo.state;
        int taskID = taskInfo.taskID;

        boolean needRefresh = doContextItemSelected(item, taskID, state);

        if (needRefresh) {
            refreshView();
        }
        return true;
    }
第二,设置布局并在片段C中绘制菜单

registerForContextMenu(transferTasksList);
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
                                ContextMenu.ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    android.view.MenuInflater inflater = mActivity.getMenuInflater();
    inflater.inflate(R.menu.upload_task_menu, menu);

    ListView listView = (ListView)v;
    AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
    TransferTaskInfo taskInfo = (TransferTaskInfo)listView.getItemAtPosition(info.position);

    android.view.MenuItem itemCancel = menu.findItem(R.id.cancel);
    android.view.MenuItem itemRetry = menu.findItem(R.id.retry);
    android.view.MenuItem itemRemove = menu.findItem(R.id.remove);
    android.view.MenuItem itemRemoveAllCancelled = menu.findItem(R.id.remove_all_cancelled);
    android.view.MenuItem itemRemoveAllFinished = menu.findItem(R.id.remove_all_finished);

    itemCancel.setVisible(false);
    itemRetry.setVisible(false);
    itemRemove.setVisible(false);
    itemRemoveAllCancelled.setVisible(false);
    itemRemoveAllFinished.setVisible(false);

    switch (taskInfo.state) {
        case INIT:
            itemCancel.setVisible(true);
            break;
        case TRANSFERRING:
            itemCancel.setVisible(true);
            break;
        case CANCELLED:
            itemRetry.setVisible(true);
            itemRemove.setVisible(true);
            itemRemoveAllCancelled.setVisible(true);
            break;
        case FAILED:
            itemRetry.setVisible(true);
            itemRemove.setVisible(true);
            break;
        case FINISHED:
            itemRemove.setVisible(true);
            itemRemoveAllFinished.setVisible(true);
            break;
    }
}
@Override
    public boolean onContextItemSelected(android.view.MenuItem item) {
        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();

        TransferService txService = mActivity.getTransferService();

        if (txService == null) {
            return false;
        }

        ListView listView = transferTasksList;
        TransferTaskInfo taskInfo = (TransferTaskInfo)listView.getItemAtPosition(info.position);
        TransferManager.TaskState state = taskInfo.state;
        int taskID = taskInfo.taskID;

        boolean needRefresh = doContextItemSelected(item, taskID, state);

        if (needRefresh) {
            refreshView();
        }
        return true;
    }
第三,通过片段C中的抽象方法
doContextItemSelected
捕获click事件

registerForContextMenu(transferTasksList);
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
                                ContextMenu.ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    android.view.MenuInflater inflater = mActivity.getMenuInflater();
    inflater.inflate(R.menu.upload_task_menu, menu);

    ListView listView = (ListView)v;
    AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
    TransferTaskInfo taskInfo = (TransferTaskInfo)listView.getItemAtPosition(info.position);

    android.view.MenuItem itemCancel = menu.findItem(R.id.cancel);
    android.view.MenuItem itemRetry = menu.findItem(R.id.retry);
    android.view.MenuItem itemRemove = menu.findItem(R.id.remove);
    android.view.MenuItem itemRemoveAllCancelled = menu.findItem(R.id.remove_all_cancelled);
    android.view.MenuItem itemRemoveAllFinished = menu.findItem(R.id.remove_all_finished);

    itemCancel.setVisible(false);
    itemRetry.setVisible(false);
    itemRemove.setVisible(false);
    itemRemoveAllCancelled.setVisible(false);
    itemRemoveAllFinished.setVisible(false);

    switch (taskInfo.state) {
        case INIT:
            itemCancel.setVisible(true);
            break;
        case TRANSFERRING:
            itemCancel.setVisible(true);
            break;
        case CANCELLED:
            itemRetry.setVisible(true);
            itemRemove.setVisible(true);
            itemRemoveAllCancelled.setVisible(true);
            break;
        case FAILED:
            itemRetry.setVisible(true);
            itemRemove.setVisible(true);
            break;
        case FINISHED:
            itemRemove.setVisible(true);
            itemRemoveAllFinished.setVisible(true);
            break;
    }
}
@Override
    public boolean onContextItemSelected(android.view.MenuItem item) {
        AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();

        TransferService txService = mActivity.getTransferService();

        if (txService == null) {
            return false;
        }

        ListView listView = transferTasksList;
        TransferTaskInfo taskInfo = (TransferTaskInfo)listView.getItemAtPosition(info.position);
        TransferManager.TaskState state = taskInfo.state;
        int taskID = taskInfo.taskID;

        boolean needRefresh = doContextItemSelected(item, taskID, state);

        if (needRefresh) {
            refreshView();
        }
        return true;
    }
我实现的抽象方法是这样的A和B

@Override
boolean doContextItemSelected(MenuItem item, int taskID, TransferManager.TaskState state) {
    switch (item.getItemId()) {
        case R.id.cancel:
            if (state == TransferManager.TaskState.INIT || state == TransferManager.TaskState.TRANSFERRING) {
                mActivity.getTransferService().cancelUploadTask(taskID);
                return true;
            }
            break;
        case R.id.retry:
            if (state == TransferManager.TaskState.FAILED || state == TransferManager.TaskState.CANCELLED) {
                mActivity.getTransferService().retryUploadTask(taskID);
                return true;
            }
            break;
        case R.id.remove:
            if (state == TransferManager.TaskState.FINISHED ||
                    state == TransferManager.TaskState.FAILED ||
                    state == TransferManager.TaskState.CANCELLED) {
                mActivity.getTransferService().removeUploadTask(taskID);
                return true;
            }
            break;
        case R.id.remove_all_cancelled:
            if (state == TransferManager.TaskState.CANCELLED) {
                mActivity.getTransferService().removeAllUploadTasksByState(TransferManager.TaskState.CANCELLED);
                return true;
            }
            break;
        case R.id.remove_all_finished:
            if (state == TransferManager.TaskState.FINISHED) {
                mActivity.getTransferService().removeAllUploadTasksByState(TransferManager.TaskState.FINISHED);
                return true;
            }
            break;
        default:
            return false;
    }
    return false;
}
它在片段A中工作得很好,当我长按片段B时,它可以弹出菜单,但当我选择菜单项时,它崩溃了

坠机日志是

java.lang.IndexOutOfBoundsException: Invalid index 1, size is 0
        at java.util.ArrayList.throwIndexOutOfBoundsException(ArrayList.java:255)
        at java.util.ArrayList.get(ArrayList.java:308)
        at com.seafile.seadroid2.ui.adapter.TransferTasksAdapter.getItem(TransferTasksAdapter.java:131)
        at com.seafile.seadroid2.ui.adapter.TransferTasksAdapter.getItem(TransferTasksAdapter.java:32)
        at android.widget.AdapterView.getItemAtPosition(AdapterView.java:764)
        at com.seafile.seadroid2.ui.fragment.TransferTaskFragment.onContextItemSelected(TransferTaskFragment.java:186)
        at android.support.v4.app.Fragment.performContextItemSelected(Fragment.java:1593)
        at android.support.v4.app.FragmentManagerImpl.dispatchContextItemSelected(FragmentManager.java:2006)
        at android.support.v4.app.FragmentActivity.onMenuItemSelected(FragmentActivity.java:370)
        at com.actionbarsherlock.app.SherlockFragmentActivity.onMenuItemSelected(SherlockFragmentActivity.java:210)

更新

此片段上用户可见提示的当前值

为了解决这个问题,在一个片段中添加条件,如下所示

@Override
    public boolean onContextItemSelected(android.view.MenuItem item) {
        if (getUserVisibleHint()) {
            //TODO something when item was selected

            return true;
        } else
            return false;
    }

我只是遇到了同样的问题。但是我写的代码和你不完全一样。我在一个活动中有两个片段(这两个片段不是从同一个祖先扩展而来),比如片段A和片段B。(在main_activity.xml中,片段A位于片段B之上,因此在logcat中,片段A总是在片段B之前创建,我从片段A和片段B中所有可调用函数的insert Log.d(…)中获得了此信息)
片段a中有一个ListView,片段B中有一个GridView。 我在片段onCreateView(..)回调中调用了registerForContextMenu(…),我还重写了片段A中的onCreateContextMenu(..)和onContextItemSelected。 我在片段B中也做了同样的事情。 现在问题来了:
1. 当我长时间单击片段B中的项(在gridview中)时,调用片段B的onCreateContextMenu(我是从日志信息中获得的),然后在弹出式上下文菜单中选择项,奇怪的是,调用片段A的onContextItemSelected。 (由于片段B中的上下文菜单项与片段A中的上下文菜单项不同,有时整个应用程序崩溃,有时什么也没发生)
2. 当我长时间单击片段A中的项(在列表视图中)时,调用片段A的onCreateContextMenu,然后选择上下文项,调用片段A的onContextItemSelected。
所以,总的来说,片段A是有效的,片段B是无效的。我发现为了解决这个问题,我们应该在片段A中的onContextItemSelected中做更多的工作

public boolean onContextItemSelected(MenuItem menuItem) { AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuItem.getMenuInfo(); try { int position = info.position; final EditText et = (EditText) mListView.getChildAt(position).findViewById(R.id.edittext); final String name = et.getText().toString(); Log.d(TAG, "haha: " + name); switch(menuItem.getItemId()){ case R.id.delete: SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(mActivity); SharedPreferences.Editor editor = pref.edit(); editor.remove(name); editor.commit(); notifyDataSetChange(); break; } } catch(Exception e){ return false; } return true; } 公共布尔值onContextItemSelected(MenuItem MenuItem){ AdapterView.AdapterContextMenuInfo信息=(AdapterView.AdapterContextMenuInfo)menuItem.getMenuInfo(); 试一试{ int位置=信息位置; final EditText et=(EditText)mListView.getChildAt(position.findViewById(R.id.EditText); 最终字符串名称=et.getText().toString(); Log.d(标签“哈哈:”+名称); 开关(menuItem.getItemId()){ 案例R.id.delete: SharedReferences pref=PreferenceManager.GetDefaultSharedReferences(MacActivity); SharedReferences.Editor=pref.edit(); 删除(姓名); commit(); notifyDataSetChange(); 打破 } } 捕获(例外e){ 返回false; } 返回true; }
当您发现选定的上下文项不是针对片段A时,从片段A中选择的onContextItemSelected返回false,那么将调用片段B中选择的onContextItemSelected。

请使用下面的技巧对项目进行排序 在fragment中使用的每个类中都添加这个

@Override
    public boolean onContextItemSelected(MenuItem item) {


 if(item.getTitle() == "Tittle you given to menu") {

// do somthing

}


}

菜单不是你的问题,你的问题在这里
TransferTasksAdapter.java:131
是的,没错。但是当我单击上下文菜单项时,它总是转到片段A,即使我在片段B中。我喜欢由
listView.getItemAtPosition(info.position)引起的错误那么你知道如何做“我在片段B中,从B的适配器获取数据类型”之类的事情吗?因为我总是使用A`s。我已经用一个解决方案更新了这个问题,希望能有所帮助。