【发布时间】:2014-12-30 13:15:30
【问题描述】:
我有两个片段 A 和 B,它们都有一个列表视图,并从基本片段 C 扩展。实际上 A 和 B 从 C 扩展了列表视图控件。
为了实现长按功能,我在 C 中注册了上下文菜单。
现在当我长按片段 A 或 B 时,上下文菜单可以按预期显示。此外,当我在片段 A 中时,上下文菜单也可以正常工作。
但我们导航到片段 B,长按列表,onContextItemSelected 方法从未被调用。
我是这样做的。
首先,在 Fragment 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捕捉点击事件。
@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;
}
在fragment A中可以正常使用,当我长按fragment 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)
更新
此片段上用户可见提示的当前值。
为了解决问题,请在您的 Fragment 之一中添加条件,如下所示。
@Override
public boolean onContextItemSelected(android.view.MenuItem item) {
if (getUserVisibleHint()) {
//TODO something when item was selected
return true;
} else
return false;
}
【问题讨论】:
-
菜单不是你的问题,你的问题在这里
TransferTasksAdapter.java:131 -
是的,完全正确。但是当我单击上下文菜单项时,即使我在片段 B 中,它也总是转到片段 A。我喜欢由
listView.getItemAtPosition(info.position);引起的错误,所以你知道如何做类似的事情,“我在片段 B 中,从 B 的适配器获取数据类型”,因为我总是使用 A。
标签: android android-fragments contextmenu long-press