轉(zhuǎn)自:http://www.open-open.com/lib/view/open1437662138631.html
原文:RecyclerView: Grid with header
GridView和ListView有許多的相似之處女淑,不過也有一個顯著的不同:沒有header和footer∠疲現(xiàn)在它們兩者都可以用RecyclerView實現(xiàn)皆刺,我想看看如何在grid上添加header鹿鳖。
GridLayoutManager
我用GridLayoutManager創(chuàng)建了一個spanCount為2的RecylcerView。
注:spanCount即列數(shù)勺良。這里GridLayoutManager的第二個參數(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以字符串的形式顯示了每個item的position憎夷,在點擊的時候顯示一個toast。
可變的span size
在上面的基本設(shè)置中躬柬,我們的spanCount為2拜轨,每個item的span size為1,因此一個header需要的span size則為2楔脯。在我嘗試著添加header之前撩轰,我想先看看如何設(shè)置?span size。其實很簡單昧廷。
注:span size表示一個item的跨度堪嫂,跨度了多少個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)在讓我們來添加一個header皆串!我們需要一個提供兩種view類型的adapter,一個為header一個為普通的item眉枕《窀矗可以看看HeaderNumberedAdapter,它在構(gòu)造函數(shù)中把一個view作為header速挑,然后把它存在一個成員變量中谤牡。
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新建一個view的時候,如果處于header的位置姥宝,我們用view holder來封裝這個header翅萤。onBindViewHolder中不必對header做任何事情,因為它的邏輯是在activity中處理的腊满。
回到activity套么。我們需要用一個header來初始化HeaderNumberedAdapter,同時重寫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,定義它的點擊事件肃弟,使用它去構(gòu)造adapter玷室。然后再setSpanSizeLookup中零蓉,我們在header所處的位置返回和span count (列數(shù))相等的?span size。
總結(jié)
為了用RecyclerView創(chuàng)建一個帶header的grid:
定義一個具有兩種view類型的adapter阵苇,一個為header一個為普通item壁公。
nflate一個header,把它傳遞給adapter绅项。
重寫GridLayoutManager中的setSpanSizeLookup紊册,在header所處的位置返回和span count (列數(shù))相等的?span size。
源碼:https://github.com/chiuki/android-recyclerview
ps:在我的g+上有人評論說如果你不需要RecyclerView的功能快耿,比如animation囊陡,reordering,staggering等掀亥,你也可以從AOSP中拷貝HeaderGridView.java撞反。
來自:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0722/3214.html