当以编程方式添加Fragment时,ContextMenu不起作用

时间:2012-08-07 11:36:24

标签: android android-fragments

我有一个ListFragment,它为其元素提供了ContextMenu。当我将这个片段放在xml-layout中时,一切正常,但是当我通过FragmentManager以编程方式添加这个ListFragment时,这只能在第一次屏幕旋转时工作。旋转屏幕后,我可以在调试器中看到Android恢复旧的ListFragment并由于

而创建一个新的ListFragment
CustomListFragment fragment = new CustomListFragment();
fragmentTransaction.add(R.id.customFragmentContainer, fragment);

创建新的ListFragment。当我长按项目以打开ContextMenu时,将调用新ListFragment的onCreateContextMenu方法,并将结果传递给旧ListFragment的onContextItemSelected方法。

我认为当我发布一些代码时会更清楚:

这是我的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;
    }
}
}

使用此活动可以正常工作:

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();
}
}

但是使用此活动它只能在第一次屏幕旋转时起作用:

    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支持库。

1 个答案:

答案 0 :(得分:0)

好的,问题是,支持库中存在内存泄漏,onContextItemSelected() - 旧片段的方法被调用。当我返回true时,较新的片段不会调用此方法。