我已经尝试过寻找解决方案,但没有发现任何符合我情况的解决方案。我有一个MainActivity,它扩展了FragmentActivity和多个ListFragments。我使用PagerSlidingTabStrip库作为slidetabs和一个ViewPager。片段没有XML布局,它们只是ListFragments,它返回ListView,因此不需要布局。
这是一个音板应用程序,长按列表项,允许用户将声音文件设置为铃声,通知或闹钟,或保存到SD卡。
现在,所有片段加载自己的数据就好了。一切似乎都没问题,但是,当我在后台加载的Fragment上使用上下文菜单时,似乎是使用了在它之前加载的第一个或前一个片段中的ListView,它是在创建它时可见的
我的意思是,说我的MainActivity开始,它加载FragmentA,并在后台FragmentB也被预加载。
在onActivityCreated方法中,对于两个片段,它使用registerForContextMenu(getListView())。
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// Data loading etc
MyAdapter adapter = new MyAdapter(getActivity(),
R.layout.data_row, data);
setListAdapter(adapter);
registerForContextMenu(getListView());
}
但似乎正在发生的事情是FragmentB调用了registerForContextMenu(getListView())并且它似乎正在使用当前活动的ListView,它是FragmentA的列表。
所以,假设我选择从上下文菜单中保存文件。我长按了FragmentB的第一项,但它试图保存FragmentA的第一项。如果我只是点击列表项,它会按照您的预期播放它自己的声音,但上下文菜单命令会使用预加载时可见的片段列表。
这是onCreateContextMenu。注意,此时它在上下文菜单标题中使用了正确的项目标题。
@Override
public void onCreateContextMenu(ContextMenu menu, View v,
ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
menu.setHeaderTitle(data.get(info.position).getDataName());
MenuInflater inflater = this.getActivity().getMenuInflater();
inflater.inflate(R.menu.context_menu, menu);
}
这是onContextItemSelected。
@Override
public boolean onContextItemSelected(MenuItem item) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
int dataID = data.get(info.position).getDataID();
String dataName = data.get(info.position).getDataName();
Activity activity = getActivity();
if(activity instanceof MainActivity) {
switch (item.getItemId()){
case R.id.context_ringtone:
((MainActivity) activity).setRingtone(dataID, dataName);
return true;
case R.id.context_notification:
((MainActivity) activity).setNotification(dataID, dataName);
return true;
case R.id.context_alarm:
((MainActivity) activity).setAlarm(dataID, dataName);
return true;
case R.id.context_sd_card:
((MainActivity) activity).saveFile(dataID, dataName);
return true;
default:
return super.onContextItemSelected(item);
}
}
return super.onContextItemSelected(item);
}
除了预加载的Fragments使用错误的ListView之外,这一切都按预期工作。
所以我正在寻找的是一种方法来确保当FragmentB在后台加载,而另一个Fragment处于活动状态时,FragmentB应该为上下文菜单注册它自己的ListView,而不是发生哪个活动的ListView在当时可见。
我尝试过使用MyFragment.this.getListView(),我尝试过使用setUserVisibleHint方法,但这些方法没有帮助。我已经尝试在onResume中执行registerForContextMenu(getListView()),希望它在Fragment变为活动状态时重新注册正确的ListView。
非常感谢任何帮助,谢谢!
答案 0 :(得分:15)
我终于搞清楚了!
事实证明,不只是为错误的ListView调用上下文菜单,正在为所有片段调用上下文菜单。
这是通过在onContextItemSelected方法中的if语句中使用getUserVisibleHint()来解决的,这样如果调用上下文菜单的Fragment不可见,它将返回false,但如果它是当前可见的Fragment,则将执行正确的代码,意味着跳过不是预期片段的片段。我曾经以不同的方式尝试过getUserVisibleHint()但是我没有从正确的角度考虑问题。
以下是解决方案的示例。
@Override
public boolean onContextItemSelected(MenuItem item) {
if (getUserVisibleHint()) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
int dataID = data.get(info.position).getDataID();
String dataName = data.get(info.position).getDataName();
Activity activity = getActivity();
if(activity instanceof MainActivity) {
switch (item.getItemId()){
case R.id.context_ringtone:
((MainActivity) activity).setRingtone(dataID, dataName);
return true;
case R.id.context_notification:
((MainActivity) activity).setNotification(dataID, dataName);
return true;
case R.id.context_alarm:
((MainActivity) activity).setAlarm(dataID, dataName);
return true;
case R.id.context_sd_card:
((MainActivity) activity).saveFile(dataID, dataName);
return true;
default:
return super.onContextItemSelected(item);
}
}
}
return false;
}
答案 1 :(得分:0)
使用registerForContextMenu(getListView())
代替使用getListView().setOnCreateContextMenuListener()
下面是一个示例:
public class ListViewFragment extends Fragment implements AdapterView.OnItemLongClickListener {
private int position;
@Override
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
getListView().setOnCreateContextMenuListener(this);
getListView().setOnItemLongClickListener(this);
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
String title = mAdapter.getTitle(position);
menu.setHeaderTitle(title);
menu.add(0, MenuIds.play, 0, getString(R.string.play));
}
@Override
public boolean onContextItemSelected(MenuItem item) {
Log.e("onContextItemSelected",String.valueOf(position));
return true;
}
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
this.position = position;
return false;
}
}