RecyclerView:實(shí)現(xiàn)帶header的grid

轉(zhuǎn)自:http://www.open-open.com/lib/view/open1437662138631.html

原文:RecyclerView: Grid with header

GridView和ListView有許多的相似之處,不過也有一個(gè)顯著的不同:沒有header和footer?,F(xiàn)在它們兩者都可以用RecyclerView實(shí)現(xiàn),我想看看如何在grid上添加header。

GridLayoutManager

我用GridLayoutManager創(chuàng)建了一個(gè)spanCount為2的RecylcerView。

注:spanCount即列數(shù)。這里GridLayoutManager的第二個(gè)參數(shù)就是spanCount。

RecyclerView?recyclerView?=?(RecyclerView)?findViewById(

R.id.recycler_view);

recyclerView.addItemDecoration(new?MarginDecoration(this));

recyclerView.setHasFixedSize(true);

recyclerView.setLayoutManager(new?GridLayoutManager(this,?2));

recyclerView.setAdapter(new?NumberedAdapter(30));

NumberedAdapter以字符串的形式顯示了每個(gè)item的position,在點(diǎn)擊的時(shí)候顯示一個(gè)toast。

GridLayoutActivity.java

可變的span size

在上面的基本設(shè)置中,我們的spanCount為2,每個(gè)item的span size為1,因此一個(gè)header需要的span size則為2。在我嘗試著添加header之前,我想先看看如何設(shè)置?span size。其實(shí)很簡(jiǎn)單。

注:span size表示一個(gè)item的跨度,跨度了多少個(gè)span。

GridLayoutManager?manager?=?new?GridLayoutManager(this,?3);

manager.setSpanSizeLookup(new?GridLayoutManager.SpanSizeLookup()?{

@Override

public?int?getSpanSize(int?position)?{

return?(3?-?position?%?3);

}

});

recyclerView.setLayoutManager(manager);

setSpanSizeLookup可以讓你根據(jù)position來設(shè)置?span size,上面代碼中的公式所得到的?span size依次是3, 2, 1, 3, 2, 1...

GridLayoutVariableSpanSizeActivity.java

頭部(header)

現(xiàn)在讓我們來添加一個(gè)header!我們需要一個(gè)提供兩種view類型的adapter,一個(gè)為header一個(gè)為普通的item??梢钥纯?a target="_blank" rel="nofollow">HeaderNumberedAdapter,它在構(gòu)造函數(shù)中把一個(gè)view作為header,然后把它存在一個(gè)成員變量中。

package?com.sqisland.android.recyclerview;

import?android.support.v7.widget.RecyclerView;

import?android.view.LayoutInflater;

import?android.view.View;

import?android.view.ViewGroup;

import?android.widget.Toast;

import?java.util.ArrayList;

import?java.util.List;

public?class?HeaderNumberedAdapter?extends?RecyclerView.Adapter?{

private?static?final?int?ITEM_VIEW_TYPE_HEADER?=?0;

private?static?final?int?ITEM_VIEW_TYPE_ITEM?=?1;

private?final?View?header;

private?final?List?labels;

public?HeaderNumberedAdapter(View?header,?int?count)?{

if?(header?==?null)?{

throw?new?IllegalArgumentException("header?may?not?be?null");

}

this.header?=?header;

this.labels?=?new?ArrayList(count);

for?(int?i?=?0;?i?<?count;?++i)?{

labels.add(String.valueOf(i));

}

}

public?boolean?isHeader(int?position)?{

return?position?==?0;

}

@Override

public?TextViewHolder?onCreateViewHolder(ViewGroup?parent,?int?viewType)?{

if?(viewType?==?ITEM_VIEW_TYPE_HEADER)?{

return?new?TextViewHolder(header);

}

View?view?=?LayoutInflater.from(parent.getContext()).inflate(R.layout.item,?parent,?false);

return?new?TextViewHolder(view);

}

@Override

public?void?onBindViewHolder(final?TextViewHolder?holder,?final?int?position)?{

if?(isHeader(position))?{

return;

}

final?String?label?=?labels.get(position?-?1);??//?Subtract?1?for?header

holder.textView.setText(label);

holder.textView.setOnClickListener(new?View.OnClickListener()?{

@Override

public?void?onClick(View?v)?{

Toast.makeText(

holder.textView.getContext(),?label,?Toast.LENGTH_SHORT).show();

}

});

}

@Override

public?int?getItemViewType(int?position)?{

return?isHeader(position)???ITEM_VIEW_TYPE_HEADER?:?ITEM_VIEW_TYPE_ITEM;

}

@Override

public?int?getItemCount()?{

return?labels.size()?+?1;

}

}

其中TextViewHolder的代碼為:

package?com.sqisland.android.recyclerview;

import?android.support.v7.widget.RecyclerView;

import?android.view.View;

import?android.widget.TextView;

public?class?TextViewHolder?extends?RecyclerView.ViewHolder?{

public?TextView?textView;

public?TextViewHolder(View?itemView)?{

super(itemView);

textView?=?(TextView)?itemView.findViewById(R.id.text);

}

}

在RecyclerView新建一個(gè)view的時(shí)候,如果處于header的位置,我們用view holder來封裝這個(gè)header。onBindViewHolder中不必對(duì)header做任何事情,因?yàn)樗倪壿嬍窃赼ctivity中處理的。

回到activity。我們需要用一個(gè)header來初始化HeaderNumberedAdapter,同時(shí)重寫setSpanSizeLookup,讓header橫跨所有列。

final?GridLayoutManager?manager?=?new?GridLayoutManager(this,?2);

recyclerView.setLayoutManager(manager);

View?header?=?LayoutInflater.from(this).inflate(

R.layout.header,?recyclerView,?false);

header.setOnClickListener(new?View.OnClickListener()?{

@Override

public?void?onClick(View?v)?{

Toast.makeText(v.getContext(),?R.string.grid_layout_header,

Toast.LENGTH_SHORT).show();

}

});

final?HeaderNumberedAdapter?adapter

=?new?HeaderNumberedAdapter(header,?30);

recyclerView.setAdapter(adapter);

manager.setSpanSizeLookup(new?GridLayoutManager.SpanSizeLookup()?{

@Override

public?int?getSpanSize(int?position)?{

return?adapter.isHeader(position)???manager.getSpanCount()?:?1;

}

});

我們inflate header,定義它的點(diǎn)擊事件,使用它去構(gòu)造adapter。然后再setSpanSizeLookup中,我們?cè)趆eader所處的位置返回和span count (列數(shù))相等的?span size。

總結(jié)

為了用RecyclerView創(chuàng)建一個(gè)帶header的grid:

定義一個(gè)具有兩種view類型的adapter,一個(gè)為header一個(gè)為普通item。

nflate一個(gè)header,把它傳遞給adapter。

重寫GridLayoutManager中的setSpanSizeLookup,在header所處的位置返回和span count (列數(shù))相等的?span size。

源碼:https://github.com/chiuki/android-recyclerview

ps:在我的g+上有人評(píng)論說如果你不需要RecyclerView的功能,比如animation,reordering,staggering等,你也可以從AOSP中拷貝HeaderGridView.java。

來自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0722/3214.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容