在ListFragment中添加Header的最佳位置

时间:2011-04-18 14:34:45

标签: android listview header adapter android-fragments

我在列表中设置自定义标题时遇到了一些问题。

我正在使用自定义适配器创建ListFragment。我的列表工作正常,但我想弄清楚片段生命周期中的哪个位置附加标题。

我知道在设置适配器之前必须添加标头。

我尝试在onActivityCreated中添加我的标题,但是每次我的Fragment从backstack返回时都会调用它,并且因为我还在onActivityCreated中设置了适配器,所以它失败了。

我尝试在onCreate中添加它,但视图层次结构在生命周期的那个阶段不可用。

我尝试在onCreateView中添加它,但我无法将从inflate返回的视图转换为ListView。所以我无法将标题添加到香草视图中。

有什么想法吗?

7 个答案:

答案 0 :(得分:33)

我不知道你是否已经解决了问题,但这是一个对我有用的解决方案:

请勿在{{1​​}}中致电ListFragment.setListAdapter()。确保你有一个可以保存标题视图的字段变量,可能是:

ListFragment.onCreate()

然后在View mheaderView; 中,对标题视图进行充气并将其分配给您的变量,如下所示:

ListFragment.onCreateView()

最后,在您的View list_root = inflater.inflate(R.layout.fragment_list, null); // Get the list header - to be added later in the lifecycle // during onActivityCreated() mheaderView = inflater.inflate(R.layout.list_header, null); return list_root; 中,您现在可以致电ListFragment.onActivityCreated()。基本上是这样的:

ListFragment.getListView().addHeaderView()

答案 1 :(得分:32)

此解决方案适用于屏幕翻转:

在onActivityCreated()中:

getListView().addHeaderView(mHeaderView);
if (mMyAdapter == null) {
    mMyAdapter = new MyAdapter(getActivity(), null);
}
setListAdapter(mMyAdapter);

在onDestroyView()

setListAdapter(null);

答案 2 :(得分:18)

我的解决方案:

public void onActivityCreated(Bundle savedInstanceState) {
    setListAdapter(null);
    getListView().addHeaderView(mHeader);
    setListAdapter(mAdapter);
}

答案 3 :(得分:2)

这是我在列表视图中处理页脚/标题的解决方案。我在保留片段中使用它。适配器在renderView()方法中初始化。此方法可以调用您需要的次数(例如,用于视图中的刷新数据)和页脚/标题可以正常工作。我在Android 2,3,4上测试了这段代码。

@Override
public void onActivityCreated(Bundle savedInstanceState)
{
    super.onActivityCreated(savedInstanceState);

    ...

    renderView();
}


@Override
public void onDestroyView()
{
    super.onDestroyView();

    // free adapter
    setListAdapter(null);
}


private void renderView()
{
    // reference
    ListView listView = getListView();

    // adapter
    if(getListAdapter()==null)
    {
        // init adapter
        mAdapter = new MyAdapter(...);
    }
    else
    {
        // refill adapter
        // this method assign array list object to adapter and call notifyDataSetChanged()
        mAdapter.refill(...);
    }

    // add footer
    setListAdapter(null);
    if(listView.getFooterViewsCount()==0)
    {
        mFooterView = getActivity().getLayoutInflater().inflate(R.layout.my_footer, null);
        listView.addFooterView(mFooterView);
    }

    // set adapter
    setListAdapter(mAdapter);
}

答案 4 :(得分:2)

作为对我有用的简短解决方案:

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);

    View headerView = getActivity().getLayoutInflater().inflate(R.layout.header, null);
    getListView().addHeaderView(headerView);

    ArrayAdapter<XY> mAdapter = createAdapter(); // create here your own adapter
    setListAdapter(mAdapter);
}

@Override
public void onDestroyView() {
    super.onDestroyView();
    setListAdapter(null);
}

答案 5 :(得分:0)

我目前在我的课程中使用以下解决方案ListFragment

1)您在类onActivityCreated中检查您的适配器(它是一个类变量)是否为空,然后实例化它。然后,给页脚充气,例如:

View footerView = View.inflate
    (getActivity(), R.layout.list_footer_loader_view, null);

你只需要这样做一次! footerView和适配器只需创建一次。我在onActivityCreated

中创建了这两个

现在到“困难部分”,将onCreate中的片段设置为:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setRetainInstance(true);
}

我喜欢在onCreate中这样做,因为它与活动无关。现在使用setRetainInstance(true),您的片段将不会在活动被销毁后重新创建,例如屏幕方向等事件。

现在,在这些行之后添加这样的页脚:

getListView().addFooterView(footerView);

然后将适配器连接到列表:

setListAdapter(adapter);

每次活动结束时都应该这样做,在onActivityCreated中执行此操作。

在片段出现时,您通常应该考虑的另一个重要事项是,每次调用活动onCreate时都不会创建片段。

例如,这样做(如果 NOT 使用supportpackage):

MyFragment myFragment  = (MyFragment)
    getFragmentManager().findFragmentByTag(tag);
if (myFragment == null) {
    myFragment = MyFragment.newInstance();
    getFragmentManager().beginTransaction().
            add(myFragment, tag).commit();
}

如果标记当然对该片段是唯一的,那么这只会创建一次片段。

答案 6 :(得分:0)

我在页眉布局高度方面遇到了一些问题,所以我遵循了这个solution

@Override
public void onActivityCreated(Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    setListAdapter(null);//avoid problems with orientation changes
    header = getActivity().getLayoutInflater().inflate(R.layout.row_diario_header,getListView(),false);
    getListView().addHeaderView(header);
    ArrayList<Notificacao> nots = new ArrayList<>();

    nots.add(new Notificacao("16/04/2015", "Test", "Erro"));
    setListAdapter(new DiarioAdapter(getActivity(), R.layout.listview_diario, nots));
}

Header是View的一个实例,DiarioAdapter是一个自定义的ArrayAdapter。

更新1

如果您遇到重复的listfragment问题,只需更改FragmentTransaction ADD for REPLACE。