最好的地方addHeaderView在ListFragment



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

我正在创建一个ListFragment与自定义适配器。我有工作良好的列表,但我试图找出在一个片段的生命周期中附加头。

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

我试着在onActivityCreated中添加我的头,但每次我的Fragment从backstack返回时都会调用它,因为我也在onActivityCreated中设置了我的适配器,它失败了。

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

我试着在onCreateView中添加它,但我不能将从膨胀返回的视图转换为ListView。所以我不能添加我的标题到香草视图。

任何想法吗?

我不知道你是否已经解决了你的问题,但这里是一个解决方案,为我工作:

不要在你的ListFragment.onCreate()中调用ListFragment.setListAdapter()。确保你有一个可以容纳标题视图的字段变量,比如:

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()。基本上是这样的:

super.onActivityCreated(savedInstanceState);
if (mheaderView != null)  this.getListView().addHeaderView(headerView);
// Don't forget to now call setListAdapter()
this.setListAdapter(listAdapter);

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

onActivityCreated ():

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

和onDestroyView()

setListAdapter(null);

我的解决方案:

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

这是我在列表视图中处理页脚/页眉的解决方案。我在保留片段中使用它。适配器在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);
}

一个对我有效的简短解决方案:

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

我目前在我的类扩展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时都创建片段。

例如,这样做(如果您的不是使用支持包):
MyFragment myFragment  = (MyFragment)
    getFragmentManager().findFragmentByTag(tag);
if (myFragment == null) {
    myFragment = MyFragment.newInstance();
    getFragmentManager().beginTransaction().
            add(myFragment, tag).commit();
}

这将只创建片段一次,如果标签是唯一的片段当然。

我在标题布局高度上遇到了一些问题,所以我遵循了这个解决方案:

@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为REPLACE

最新更新