我有一个 ListFragment 为其元素提供 ContextMenu。当我将此片段放在 xml 布局中时,一切正常,但是当我通过 FragmentManager 以编程方式添加此 ListFragment 时,这仅在第一次屏幕旋转之前有效。旋转屏幕后,我可以在调试器中看到 Android 恢复了旧的 ListFragment 并创建了一个新的,原因是
CustomListFragment fragment = new CustomListFragment();
fragmentTransaction.add(R.id.customFragmentContainer, fragment);
创建一个新的 ListFragment 的地方。当我长按一个项目打开 ContextMenu 时,onCreateContextMenu
会调用新 ListFragment 的方法,并将结果传递给onContextItemSelected
旧 ListFragment 的方法。
我认为当我发布一些代码时它会变得更清楚:
这是我的 ListFragment:
public class CustomListFragment extends ListFragment {
private LayoutInflater layoutInflater;
private OnSelectedListener<String> selectionListener;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
layoutInflater = inflater;
return inflater.inflate(R.layout.list_fragment_layout, null);
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setListAdapter(new CustomListAdapter());
registerForContextMenu(getListView());
}
public void setOnSelectedListener(OnSelectedListener<String> listener) {
selectionListener = listener;
}
private static final String item0 = "item0";
private static final String item1 = "item1";
@Override
public void onCreateContextMenu (ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
menu.add(0, 0, 0, item0);
menu.add(0, 1, 0, item1);
}
@Override
public boolean onContextItemSelected(MenuItem menuItem) {
String selection;
if (menuItem.getItemId()==0)
selection = item0;
else
selection = item1;
if (selectionListener!=null)
selectionListener.onSelected(selection);
return true;
}
private class CustomListAdapter extends BaseAdapter {
private List<String> elemente = new ArrayList<String>();
public CustomListAdapter() {
elemente.add("one");
elemente.add("two");
elemente.add("three");
}
@Override
public int getCount() {
return elemente.size();
}
@Override
public Object getItem(int position) {
return elemente.get(position);
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView==null)
convertView = layoutInflater.inflate(R.layout.element, null);
TextView tv = (TextView)convertView;
tv.setText(elemente.get(position));
return tv;
}
}
}
有了这个 Activity 它工作正常:
public class CustomFragmentActivity extends FragmentActivity implements OnSelectedListener<String> {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_layout);
FragmentManager fragmentManager = getSupportFragmentManager();
CustomListFragment fragment = (CustomListFragment)fragmentManager.findFragmentById(R.id.customFragment);
fragment.setOnSelectedListener(this);
}
@Override
public void onSelected(String selection) {
Toast.makeText(this, selection, Toast.LENGTH_LONG).show();
}
}
但是有了这个 Activity 它只在第一次屏幕旋转之前有效:
public class CustomFragmentContainerActivity extends FragmentActivity implements OnSelectedListener<String> {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.fragment_container_layout);
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
CustomListFragment fragment = new CustomListFragment();
fragmentTransaction.add(R.id.customFragmentContainer, fragment);
fragmentTransaction.commit();
fragment.setOnSelectedListener(this);
}
@Override
public void onSelected(String selection) {
Toast.makeText(this, selection, Toast.LENGTH_LONG).show();
}
}
OnSelectedListener 只是一个提供一个公共方法的接口。屏幕旋转后,结果(所选项目)被传递给旧的 ListFragment。但是这个旧的 ListFragment 是由 Android 系统重新创建的,并且 selectionListener 为 null,所以什么也没有发生。界面如下所示:
public interface OnSelectedListener<V> {
public void onSelected(V selection);
}
最后,也许我应该提到我正在使用 v4 支持库。