android RecycleView复杂多条目的布局
用RecycleView来实现布局形式。默认仅仅能指定一种布局格式。可是实际中我们的布局常常会用到多种类型的布局方式。怎样实现呢?
今天来说下经常使用的2钟方式。
第一种:
通过自己定义addHeadView方法来加入头布局
RecycleViewWithHead.java
import android.app.Activity; import android.os.Bundle; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.GridLayoutManager.SpanSizeLookup; import android.support.v7.widget.RecyclerView; import android.view.View; public class RecycleViewWithHead extends Activity { private RecyclerView rcv; // 当前的条目是recyclerView的头布局 public static final int HEADER_RECYCLER_VIEW_ITEM = 0; // 当前的条目是普通recyclerView的条目 public static final int NORMAL_RECYCLER_VIEW_ITEM = 1; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.activity_recycle); rcv = (RecyclerView) findViewById(R.id.rcv); // 设置布局管理 GridLayoutManager manager = new GridLayoutManager(this, 2); // 设置布局管理一条数据占用几行,假设是头布局则头布局自己占用一行 manager.setSpanSizeLookup(new SpanSizeLookup() { @Override public int getSpanSize(int postion) { if (postion == 0) { return 2; } else { return 1; } } }); rcv.setLayoutManager(manager); MyRecycleAdapter adapter = new MyRecycleAdapter( RecycleViewWithHead.this, 20); View view = View.inflate(this, R.layout.head, null); adapter.addHeadView(view); rcv.setAdapter(adapter); } }
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/rcv" android:layout_width="match_parent" android:layout_height="wrap_content" /> </RelativeLayout>
<?xml version="1.0" encoding="utf-8"?
> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <ImageView android:id="@+id/iv_head" android:layout_width="80dp" android:layout_height="80dp" android:layout_margin="10dp" android:src="@drawable/head" /> <TextView android:id="@+id/tv_head" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignTop="@+id/iv_head" android:layout_toRightOf="@+id/iv_head" android:text="这是一张熊猫的图片" /> <ImageView android:id="@+id/iv_head_bottom" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignBottom="@+id/iv_head" android:layout_toRightOf="@+id/iv_head" android:src="@drawable/type" /> </RelativeLayout>
适配器MyRecycleAdapter.java
import android.content.Context; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView.ViewHolder; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Toast; public class MyRecycleAdapter extends RecyclerView.Adapter<MyRecycleAdapterHolder> { private View headView; private Context mContext; private int count; MyRecycleAdapter(Context mContext, int count) { this.count = count; this.mContext = mContext; } /** * 设置数据源总的条目 */ @Override public int getItemCount() { //返回条目数加头布局个数 return count + 1; } @Override public void onBindViewHolder(MyRecycleAdapterHolder holder, final int position) { int itemViewType = getItemViewType(position); // 头部 if (itemViewType == RecycleViewWithHead.HEADER_RECYCLER_VIEW_ITEM) { return; } else if (itemViewType == RecycleViewWithHead.NORMAL_RECYCLER_VIEW_ITEM) {//普通条目 holder.iv_item_icon.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(mContext, (position - 1) + "", 0).show(); } }); } } @Override public MyRecycleAdapterHolder onCreateViewHolder(ViewGroup parent, int viewType) { View root = null; if (viewType == RecycleViewWithHead.HEADER_RECYCLER_VIEW_ITEM) { root = headView; } else { root = LayoutInflater.from(mContext).inflate(R.layout.item, parent, false); } return new MyRecycleAdapterHolder(root, viewType); } /** * 加入自己定义头部 */ public void addHeadView(View view) { this.headView = view; } @Override public int getItemViewType(int position) { if (position == 0) { return RecycleViewWithHead.HEADER_RECYCLER_VIEW_ITEM; } else { return RecycleViewWithHead.NORMAL_RECYCLER_VIEW_ITEM; } } }
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ll_list" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="2dp" android:layout_marginRight="2dp" android:layout_marginTop="5dp" android:orientation="vertical" > <ImageView android:id="@+id/iv_item_icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/item" /> <TextView android:id="@+id/tv_item" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="5dp" android:text="这是一仅仅熊猫" /> </LinearLayout>
普通条目的ViewHolder
import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.ImageView; import android.widget.TextView; public class MyRecycleAdapterHolder extends RecyclerView.ViewHolder{ public ImageView iv_item_icon; public TextView tv_item; public MyRecycleAdapterHolder(View itemView) { super(itemView); } public MyRecycleAdapterHolder(View itemView,int viewType) { super(itemView); initView(itemView,viewType); } private void initView(View itemView, int viewType) { iv_item_icon = (ImageView) itemView.findViewById(R.id.iv_item_icon); tv_item = (TextView) itemView.findViewById(R.id.tv_item); } }
效果图:
另一种情况类似于淘宝的商品展示我们能够切换每行显示的数量,事实上也非常easy
先看下要实现的效果:
我先说下大致的实现思路:
1.给adapter设置一个当前显示多行还是单行的标记。
2.每次切换视图时重置标记。并重置RecycleView的LayoutManager。
3.调用adapter.notifyItemRangeChanged(2, adapter.getItemCount());(第一个參数是动画開始的位置索引)
好了再来看下RecycleViewWithHead.java
import com.example.myrecycleviewdemo.adapter.MyRecycleAdapter; import android.app.Activity; import android.os.Bundle; import android.support.v7.widget.GridLayoutManager; import android.support.v7.widget.GridLayoutManager.SpanSizeLookup; import android.support.v7.widget.RecyclerView; import android.view.View; import android.view.View.OnClickListener; import android.widget.ImageView; public class RecycleViewWithHead extends Activity implements OnClickListener { private RecyclerView rcv; // 当前的条目是recyclerView的头布局 public static final int HEADER_RECYCLER_VIEW_ITEM = 0; // 当前的条目是普通recyclerView的条目 public static final int NORMAL_RECYCLER_VIEW_ITEM = 1; // 一行显示一个 public static final int RECYCLER_VIEW_ITEM_SINGLE = 3; // 一行显示两个 public static final int RECYCLER_VIEW_ITEM_DOUBLE = 4; private ImageView iv_switch;// 视图转换 private MyRecycleAdapter adapter; private GridLayoutManager manager; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.activity_recycle); rcv = (RecyclerView) findViewById(R.id.rcv); iv_switch = (ImageView) findViewById(R.id.iv_switch); iv_switch.setOnClickListener(this); manager = new GridLayoutManager(this, 2); // 设置布局管理一条数据占用几行,假设是头布局则头布局自己占用一行 manager.setSpanSizeLookup(new SpanSizeLookup() { @Override public int getSpanSize(int postion) { if (postion == 0) { return 2; } else { return 1; } } }); rcv.setLayoutManager(manager); adapter = new MyRecycleAdapter(RecycleViewWithHead.this, 20); View view = View.inflate(this, R.layout.head, null); // 设置当前ViewType adapter.setSpanSize(RecycleViewWithHead.RECYCLER_VIEW_ITEM_DOUBLE); adapter.addHeadView(view); rcv.setAdapter(adapter); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.iv_switch: changeRecycleViewList(); break; default: break; } } /** * 改变RecycleView的显示列数 */ private void changeRecycleViewList() { if (adapter != null) { int spanSize = adapter.getSpanSize(); // 当前一行显示一列 if (spanSize == RecycleViewWithHead.RECYCLER_VIEW_ITEM_SINGLE) { manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { if (adapter.getItemViewType(position) == RecycleViewWithHead.HEADER_RECYCLER_VIEW_ITEM) { return 2; } else { return 1; } } }); adapter.setSpanSize(RecycleViewWithHead.RECYCLER_VIEW_ITEM_DOUBLE); } // 当前一行显示两列 else if (spanSize == RecycleViewWithHead.RECYCLER_VIEW_ITEM_DOUBLE) { manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { if (adapter.getItemViewType(position) == RecycleViewWithHead.HEADER_RECYCLER_VIEW_ITEM) { return 2; } else { return 2; } } }); adapter.setSpanSize(RecycleViewWithHead.RECYCLER_VIEW_ITEM_SINGLE); } // 第一个參数是动画開始的位置索引 adapter.notifyItemRangeChanged(2, adapter.getItemCount()); } } }
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/rcv" android:layout_width="match_parent" android:layout_height="wrap_content" /> <ImageView android:id="@+id/iv_switch" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_alignParentRight="true" android:layout_margin="20dp" android:src="@drawable/more" /> </RelativeLayout>
适配器MyRecycleAdapter.java
import com.example.myrecycleviewdemo.R; import com.example.myrecycleviewdemo.RecycleViewWithHead; import com.example.myrecycleviewdemo.R.layout; import android.content.Context; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView.ViewHolder; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.Toast; public class MyRecycleAdapter extends RecyclerView.Adapter<MyRecycleAdapterHolder> { public View headView; public Context mContext; public int count; private int spanSize;// 当前每行显示几列 public MyRecycleAdapter(Context mContext, int count) { this.count = count; this.mContext = mContext; } /** * 设置数据源总的条目 */ @Override public int getItemCount() { // 返回条目数加头布局个数 return count + 1; } @Override public void onBindViewHolder(MyRecycleAdapterHolder holder, final int position) { int itemViewType = getItemViewType(position); // 头部 if (itemViewType == RecycleViewWithHead.HEADER_RECYCLER_VIEW_ITEM) { return; } else {// 普通条目 if (itemViewType == RecycleViewWithHead.RECYCLER_VIEW_ITEM_DOUBLE) {// 一行两列视图 holder.iv_item_icon.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(mContext, "2列。" + (position - 1) + "", 0) .show(); } }); } else if (itemViewType == RecycleViewWithHead.RECYCLER_VIEW_ITEM_SINGLE) {// 一行一列视图 holder.iv_item_icon_single.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Toast.makeText(mContext,"单列," + (position - 1) + "", 0).show(); } }); } } } @Override public MyRecycleAdapterHolder onCreateViewHolder(ViewGroup parent, int viewType) { View root = null; // 头部 if (viewType == RecycleViewWithHead.HEADER_RECYCLER_VIEW_ITEM) { root = headView; } else {// 普通条目 /** 一行显示一条 */ if (viewType == RecycleViewWithHead.RECYCLER_VIEW_ITEM_SINGLE) { root = LayoutInflater.from(mContext).inflate(R.layout.item_single, parent, false); } /** 一行显示两条 */ else { root = LayoutInflater.from(mContext).inflate(R.layout.item_double, parent, false); } } return new MyRecycleAdapterHolder(root, viewType); } /** * 加入自己定义头部 */ public void addHeadView(View view) { this.headView = view; } @Override public int getItemViewType(int position) { if (position == 0) { return RecycleViewWithHead.HEADER_RECYCLER_VIEW_ITEM; } else { /** 一行显示一条 */ if (spanSize == RecycleViewWithHead.RECYCLER_VIEW_ITEM_SINGLE) { return RecycleViewWithHead.RECYCLER_VIEW_ITEM_SINGLE; /** 一行显示两条 */ } else { return RecycleViewWithHead.RECYCLER_VIEW_ITEM_DOUBLE; } } } public int getSpanSize() { return spanSize; } public void setSpanSize(int spanSize) { this.spanSize = spanSize; } }
普通条目的ViewHolder
import com.example.myrecycleviewdemo.R; import com.example.myrecycleviewdemo.R.id; import com.example.myrecycleviewdemo.RecycleViewWithHead; import android.support.v7.widget.RecyclerView; import android.view.View; import android.widget.ImageView; import android.widget.TextView; public class MyRecycleAdapterHolder extends RecyclerView.ViewHolder{ //一行两列视图 public ImageView iv_item_icon; public TextView tv_item; //一行一列视图 public ImageView iv_item_icon_single; public TextView tv_item_single; public MyRecycleAdapterHolder(View itemView) { super(itemView); } public MyRecycleAdapterHolder(View itemView,int viewType) { super(itemView); initView(itemView,viewType); } private void initView(View itemView, int viewType) { if(viewType == RecycleViewWithHead.RECYCLER_VIEW_ITEM_DOUBLE){ iv_item_icon = (ImageView) itemView.findViewById(R.id.iv_item_icon); tv_item = (TextView) itemView.findViewById(R.id.tv_item); }else if(viewType == RecycleViewWithHead.RECYCLER_VIEW_ITEM_SINGLE){ iv_item_icon_single = (ImageView) itemView.findViewById(R.id.iv_item_icon_single); tv_item_single = (TextView) itemView.findViewById(R.id.tv_item_single); } } }
头布局文件head.xm没有不论什么变化
条目的布局拆分为2个item_double.xml和item_single.xml
item_double.xml和之前的item.xml一样。
item_single.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ll_list" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="2dp" android:layout_marginRight="2dp" android:layout_marginTop="5dp" android:orientation="horizontal" > <ImageView android:id="@+id/iv_item_icon_single" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/item" /> <TextView android:id="@+id/tv_item_single" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginTop="5dp" android:text="这是一仅仅熊猫" /> </LinearLayout>
源代码地址:http://download.csdn.net/detail/linder_qzy/9491370