一、核心思想
根据Adapter的getItemViewType( )返回结果的不同来返回我们的item数量、ViewHolder.
二、代码
(1)MainActivity布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
(2)item布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:background="#ff33b5e5"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center"
tools:text="别看了,我就是一个TextView" />
</RelativeLayout>
(3)Header和Footer的布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@android:color/holo_orange_light"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center"
android:text="我是头布局" />
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:background="@android:color/holo_orange_light"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="40dp"
android:gravity="center"
android:text="我是脚布局" />
</RelativeLayout>
(4)MainActivity中
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private MainAdapter mAdapter;
private List<String> mDatas;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
mRecyclerView = (RecyclerView) findViewById(R.id.recyclerview);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
mRecyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL));
mAdapter = new MainAdapter(this,mDatas);
mRecyclerView.setAdapter(mAdapter);
//添加Header和Footer
addHeader();
addFooter();
}
private void addHeader() {
View v = LayoutInflater.from(this).inflate(R.layout.item_header, mRecyclerView, false);
mAdapter.setHeaderView(v);
}
private void addFooter() {
View v = LayoutInflater.from(this).inflate(R.layout.item_footer, mRecyclerView, false);
mAdapter.setFooterView(v);
}
private void initData() {
mDatas = new ArrayList<>();
for (int i = 'A'; i < 'Z'; i++) {
mDatas.add("" + (char) i);
}
}
}
(6)MainAdapter 中
public class MainAdapter extends RecyclerView.Adapter<MainAdapter.MyViewHolder> {
private Context mContext;
private List<String> mDatas;
//定义三种类型来对应我们的Header、正常布局、Footer
public static final int TYPE_HEADER = 0;
public static final int TYPE_NORMAL = 1;
public static final int TYPE_FOOTER = 2;
private View mHeaderView;
private View mFooterView;
public MainAdapter(Context context, List<String> mDatas) {
this.mContext = context;
this.mDatas = mDatas;
}
public void setHeaderView(View headerView) {
mHeaderView = headerView;
notifyItemInserted(0);//注意这里
}
public View getHeaderView() {
return mHeaderView;
}
public void setFooterView(View footerView) {
mFooterView = footerView;
notifyItemInserted(getItemCount()-1);//注意这里
}
public View getFooterView() {
return mFooterView;
}
/**
* 重写了getItemViewType方法,根据位置返回不同的ViewType
*/
@Override
public int getItemViewType(int position) {
if (mHeaderView == null && mFooterView == null) {
return TYPE_NORMAL;
}
if (position == 0) {
return TYPE_HEADER;
}
if (position == getItemCount() - 1) {
return TYPE_FOOTER;
}
return TYPE_NORMAL;
}
/**
* 根据不同的ViewType返回不同的item数量
*/
@Override
public int getItemCount() {
if(mHeaderView == null && mFooterView == null){
return mDatas.size();
}else if(mHeaderView == null && mFooterView != null){
return mDatas.size() + 1;
}else if (mHeaderView != null && mFooterView == null){
return mDatas.size() + 1;
}else {
return mDatas.size() + 2;
}
}
/**
* 根据不同的ViewType创建不同的ViewHolder对象
*/
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if(mHeaderView != null && viewType == TYPE_HEADER) {
return new MyViewHolder(mHeaderView);
}
if(mFooterView != null && viewType == TYPE_FOOTER){
return new MyViewHolder(mFooterView);
}
return new MyViewHolder(LayoutInflater.from(mContext).inflate(R.layout.item_layout, parent, false));
}
@Override
public void onBindViewHolder(MyViewHolder holder, final int position) {
if (getItemViewType(position) == TYPE_HEADER) {
return;
} else if (getItemViewType(position) == TYPE_FOOTER) {
return;
} else if (getItemViewType(position) == TYPE_NORMAL) {
if (mHeaderView == null) {
holder.tv.setText(mDatas.get(position));
} else {
holder.tv.setText(mDatas.get(position - 1));
}
}
}
/**
* 这里Header和Footer很简单,就不单独为Header和Footer创建一个ViewHolder了
*/
class MyViewHolder extends RecyclerView.ViewHolder {
TextView tv;
public MyViewHolder(View view) {
super(view);
if (itemView == mHeaderView){
return;
}
if (itemView == mFooterView){
return;
}
tv = (TextView)itemView.findViewById(R.id.tv);
}
}
}
三、效果图
四、GridLayoutManager添加Header和Footer
我们在MainActivity中把LinearLayoutManager换成GridLayoutManager看一看效果
mRecyclerView.setLayoutManager(new GridLayoutManager(this, 2));
//mRecyclerView.addItemDecoration(new DividerItemDecoration(this,DividerItemDecoration.VERTICAL));
//默认的分隔线不再适应GridLayoutManager了,这里注释掉
Header和Footer竟然和普通item跑到一排了......
此时:要用到GridLayoutManager的一个方法setSpanSizeLookup:
gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return 0;
}
});
这个方法需要一个SpanSizeLookup对象,SpanSizeLookup是一个定义在GridLayoutManager中抽象类,只有一个抽象方法getSpanSize(),
这个方法的返回值决定了我们每个position上的item占据的单元格个数.
正常情况下每个item占据1个单元格,结合GridLayoutManager构造方法中设置的每行的个数new GridLayoutManager(this, 2), 如果当前位置是Header和Footer的话,那么该item占据2个单元格,.
ok,了解了这个方法的话就可以来解决问题了
在Adapter中重写onAttachedToRecyclerView()方法:
@Override
public void onAttachedToRecyclerView(RecyclerView recyclerView) {
super.onAttachedToRecyclerView(recyclerView);
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
if (layoutManager instanceof GridLayoutManager){
final GridLayoutManager gridManager = ((GridLayoutManager) layoutManager);
gridManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
if (getItemViewType(position) == TYPE_HEADER){
return gridManager.getSpanCount();
}else if (getItemViewType(position) == TYPE_FOOTER){
return gridManager.getSpanCount();
}else{
return 1;
}
}
});
}
}
在来看一看效果:
ok,完美解决
五、StaggeredGridLayoutManager添加Header和Footer
在StaggeredGridLayoutManager中并没有像GridLayoutManager中这样的方法,这里可以通过StaggeredGridLayoutManager.LayoutParams的一个方法setFullSpan(boolean fullSpan)来设置占领全部空间.
同样:
在Adapter中重写onViewAttachedToWindow()方法:
@Override
public void onViewAttachedToWindow(MyViewHolder holder) {
super.onViewAttachedToWindow(holder);
ViewGroup.LayoutParams lp = holder.itemView.getLayoutParams();
if( lp != null && lp instanceof StaggeredGridLayoutManager.LayoutParams ) {
StaggeredGridLayoutManager.LayoutParams params =(StaggeredGridLayoutManager.LayoutParams) lp;
if(holder.getItemViewType()==TYPE_HEADER || holder.getItemViewType()==TYPE_FOOTER){
params.setFullSpan(true);
}else{
params.setFullSpan(false);
}
}
}
ok,解决了.
网友评论