簡體   English   中英

ListFragment中addHeaderView的最佳位置

[英]Best place to addHeaderView in ListFragment

我在列表中設置自定義標題時遇到了麻煩。

我正在使用自定義適配器創建ListFragment。 我的列表工作正常,但是我想弄清楚Fragment在生命周期中的何處附加標頭。

我知道在設置適配器之前必須先添加標題。

我嘗試將標頭添加到onActivityCreated中,但是每次我的Fragment從后堆棧返回時都會調用該標頭,並且由於我也在onActivityCreated中設置了適配器,所以它失敗了。

我嘗試在onCreate中添加它,但是視圖層次結構在生命周期的那個階段不可用。

我嘗試在onCreateView中添加它,但無法將從膨脹返回的視圖轉換為ListView。 所以我不能將標題添加到香草視圖。

有什么想法嗎?

我不知道您是否已解決問題,但以下是對我有用的解決方案:

不要在ListFragment.setListAdapter()中調用ListFragment.onCreate() 確保您有一個可以保存標題視圖的字段變量,例如:

View mheaderView;

然后在您的ListFragment.onCreateView() ,將標題View膨脹,並將其分配給您的變量,如下所示:

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都創建片段。

例如,執行此操作(如果您使用supportpackage):

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

標頭是View的實例,而DiarioAdapter是自定義ArrayAdapter。

更新1

如果您對重復的片段片段有疑問,只需更改FragmentTransaction ADD for REPLACE。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM