我有两个片段A和B,它们都有一个列表视图,并从基本片段C扩展。实际上A和B从C扩展了listview控件。
我在O中注册了C中的上下文菜单,以实现长按功能。
现在,当我长按片段A或B时,上下文菜单可以按预期显示。此外,当我在片段A中时,上下文菜单也可以作为例外工作。
但是我们导航到片段B,长按列表,onContextItemSelected
方法从未调用过。
我是这样做的。
首先,在片段C中的onActivityCreated
中注册上下文菜单。
registerForContextMenu(transferTasksList);
其次,设置布局并在Fragment C中绘制菜单。
@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;
}
}
第三,通过Fragment C中的抽象方法doContextItemSelected
捕获click事件。
@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;
}
答案 0 :(得分:1)
我刚遇到同样的问题。但我没有写出与你完全相同的代码。我在一个活动中有两个片段(这两个片段不会从同一个祖先延伸),比如片段A和片段B.(在main_activity.xml片段A中,片段B在片段B之上,因此在logcat中,片段A始终是在片段B之前创建,我从片段A和片段B中的所有可调用函数中插入Log.d(...)获得此信息
片段A中有一个ListView,片段B中有一个GridView。
我在片段onCreateView(..)回调中调用了registerForContextMenu(...),我还覆盖片段A中的onCreateContextMenu(..)和onContextItemSelected。
我在片段B中做了同样的事情。
现在出现了问题:
1。
当我长时间点击片段B中的项目(在网格视图中)时,调用片段B的onCreateContextMenu(我从日志信息中得到这个),然后我在弹出的上下文菜单中选择项目,奇怪的是,片段A的onContextItemSelected被调用。
(由于片段B中的上下文菜单项与片段A中的上下文菜单项不同,有时整个应用程序崩溃,有时没有发生任何事情)
2。
当我长时间点击片段A中的项目(在列表视图中)时,调用片段A的onCreateContextMenu,然后选择上下文项目,调用片段A的onContextItemSelected。
因此,总的来说,片段A是有效的,片段B是不起作用的。我发现为了解决这个问题,我们应该在片段A
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; }
如果您发现所选的上下文项未定位到片段A,则会从片段A的onContextItemSelected中返回false,然后将调用片段B中的onContextItemSelected。
答案 1 :(得分:0)
请使用下面的Trick对项目进行排序 在片段
中使用的每个类中添加它@Override
public boolean onContextItemSelected(MenuItem item) {
if(item.getTitle() == "Tittle you given to menu") {
// do somthing
}
}