Android RecycleView实现混合Item布局
首先来看看效果吧:
![](http://upload-images.jianshu.io/upload_images/2178834-67e92f6c058813df.png)
效果预览.png
本实例来自于慕课网的视屏http://www.imooc.com/video/13046,实现步骤可以自己去观看视屏,这里只记录了下实现的代码。
添加依赖:
(1) 在项目的build.gradle文件中添加下面的依赖
compile 'com.android.support:recyclerview-v7:25.0.0'
(2) 也可以在下图中自动进行依赖,选择RecycleView即可。
![](http://upload-images.jianshu.io/upload_images/2178834-2b7a22a05fa333c1.png)
代码部分
直接代码传送门
MainActivity
public class MainActivity extends AppCompatActivity { private RecyclerView mRecyclerView; private MyAdapter mMyAdapter; private int colors[] = {android.R.color.holo_blue_bright,android.R.color.black,android.R.color.holo_red_dark}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initData(); } private void initView() { mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerView); mRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)); mMyAdapter = new MyAdapter(this); mRecyclerView.setAdapter(mMyAdapter); } private void initData() { List<Person> list= new ArrayList<>(); for (int i = 0; i < 20; i++) { Person p = new Person(); int type = (int) (Math.random()*3+1); p.type = type; p.content="content"+1; p.avaterColor = colors[type-1]; p.name = "name"+i; list.add(p); } mMyAdapter.addList(list); mMyAdapter.notifyDataSetChanged(); } }
bean对象Person类
/** * Created by 24540 on 2017/3/13. */ public class Person { public static final int TYPE_ONE = 1; public static final int TYPE_TWO = 2; public static final int TYPE_THREE = 3; protected int type; protected int avaterColor; protected int contentColor; protected String name; protected String content; public String getContent() { return content; } public void setContent(String content) { this.content = content; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getContentColor() { return contentColor; } public void setContentColor(int contentColor) { this.contentColor = contentColor; } public int getAvaterColor() { return avaterColor; } public void setAvaterColor(int avaterColor) { this.avaterColor = avaterColor; } public int getType() { return type; } public void setType(int type) { this.type = type; } public static int getTypeThree() { return TYPE_THREE; } public static int getTypeTwo() { return TYPE_TWO; } public static int getTypeOne() { return TYPE_ONE; } }
RecycleView的适配器
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { private LayoutInflater mLayoutInflater; private List<Person> mList = new ArrayList<>(); private Context mContext; public MyAdapter(Context mContext) { this.mContext = mContext; mLayoutInflater = LayoutInflater.from(mContext); } //使用此方法从获取数据 public void addList(List<Person> list){ mList.addAll(list); } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { //根据不同的viewType,创建并返回影响的ViewHolder switch (viewType){ case Person.TYPE_ONE: return new TypeOneHolder(mLayoutInflater.inflate(R.layout.item_type_one,parent,false)); case Person.TYPE_TWO: return new TypeTwoHolder(mLayoutInflater.inflate(R.layout.item_type_two,parent,false)); case Person.TYPE_THREE: return new TypeThreeHolder(mLayoutInflater.inflate(R.layout.item_type_three,parent,false)); } return null; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { //抽象出TypeAbstartViewHolder,所以在进行绑定的时候可以直接调用 ((TypeAbstartViewHolder)holder).bindHolder(mList.get(position)); } @Override public int getItemViewType(int position) { return mList.get(position).getType(); } @Override public int getItemCount() { return mList.size(); } }
关键的一点,TypeAbstartViewHolder 抽象出bindHolder方法,优雅实现加载不同item布局,代码如下:
public abstract class TypeAbstartViewHolder extends RecyclerView.ViewHolder { public TypeAbstartViewHolder(View itemView) { super(itemView); } public abstract void bindHolder(Person person); }
继承自上面抽象的方法,实现加载不同item布局TypeOneHolder:
public class TypeOneHolder extends TypeAbstartViewHolder { private ImageView avater; private TextView name; public TypeOneHolder(View itemView) { super(itemView); avater = (ImageView) itemView.findViewById(R.id.avater); name = (TextView) itemView.findViewById(R.id.name); } //为ViewHolder绑定数据 @Override public void bindHolder(Person person) { avater.setBackgroundResource(person.getAvaterColor()); name.setText(person.getName()); } }
TypeTwoHolde代码如下:
public class TypeTwoHolder extends TypeAbstartViewHolder { private ImageView avater; private TextView name; private TextView content; public TypeTwoHolder(View itemView) { super(itemView); avater = (ImageView) itemView.findViewById(R.id.avater); name = (TextView) itemView.findViewById(R.id.name); content = (TextView) itemView.findViewById(R.id.content); } //为ViewHolder绑定数据 @Override public void bindHolder(Person person) { avater.setBackgroundResource(person.getAvaterColor()); name.setText(person.getName()); content.setText(person.getContent()); } }
TypeThreeHolder的代码如下:
public class TypeThreeHolder extends TypeAbstartViewHolder { private ImageView avater; private TextView name; private TextView content; private ImageView iv; public TypeThreeHolder(View itemView) { super(itemView); avater = (ImageView) itemView.findViewById(R.id.avater); name = (TextView) itemView.findViewById(R.id.name); content = (TextView) itemView.findViewById(R.id.content); iv = (ImageView) itemView.findViewById(R.id.content_color); } //为ViewHolder绑定数据 @Override public void bindHolder(Person person) { avater.setBackgroundResource(person.getAvaterColor()); name.setText(person.getName()); content.setText(person.getContent()); iv.setBackgroundResource(person.getAvaterColor()); } }
xml文件代码部分:只放出了item_type_three部分的代码:
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:background="@android:color/white" android:layout_width="match_parent" android:gravity="center_vertical" android:layout_height="60dp"> <ImageView android:id="@+id/avater" android:layout_marginLeft="4dp" android:layout_width="40dp" android:layout_height="40dp"/> <LinearLayout android:layout_toRightOf="@id/avater" android:layout_marginLeft="5dp" android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:id="@+id/name" android:text="type_one_textview" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:id="@+id/content" android:layout_marginTop="5dp" android:text="type_one_textview" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout> <ImageView android:layout_alignParentRight="true" android:layout_marginRight="10dp" android:id="@+id/content_color" android:layout_width="100dp" android:layout_height="40dp"/> </RelativeLayout>
通过recycleView实现两个不同布局混搭,只需要修改mainActivity如下:
public class MainActivity extends AppCompatActivity { private RecyclerView mRecyclerView; private MyAdapter mMyAdapter; private int colors[] = {android.R.color.holo_blue_bright, android.R.color.black, android.R.color.holo_red_dark}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initData(); } private void initView() { mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerView); //构造参数里面的2表示的是一行有两列 final GridLayoutManager manager = new GridLayoutManager(this, 2); mRecyclerView.setLayoutManager(manager); manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { int type = mRecyclerView.getAdapter().getItemViewType(position); //若是TYPE_THREE,占用两列,否则占用一列 if (type == Person.TYPE_THREE) { return manager.getSpanCount(); } else { return 1; } } }); mMyAdapter = new MyAdapter(this); //给布局里的子view添加边距 mRecyclerView.addItemDecoration(new RecyclerView.ItemDecoration() { @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { GridLayoutManager.LayoutParams layoutParams = (GridLayoutManager.LayoutParams) view.getLayoutParams(); int spanSize = layoutParams.getSpanSize(); int spanIndex = layoutParams.getSpanIndex(); outRect.top = 20; if (spanSize != manager.getSpanCount()) { if (spanIndex == 0) { outRect.right = 0; } else { outRect.right = 10; } } } }); mRecyclerView.setAdapter(mMyAdapter); } private void initData() { List<Person> list = new ArrayList<>(); for (int i = 0; i < 20; i++) { Person p = new Person(); int type = (int) (Math.random() * 3 + 1); p.type = type; p.content = "content" + 1; p.avaterColor = colors[type - 1]; p.name = "name" + i; list.add(p); } mMyAdapter.addList(list); mMyAdapter.notifyDataSetChanged(); } }
效果如图:
![](http://upload-images.jianshu.io/upload_images/2178834-261956ebf30eb7e4.png)
两种布局.png
分类:
android
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!
2017-07-10 Android 用Socket实现PC和手机的文件传输
2016-07-10 win7如何修改磁盘驱动器号,怎么修改磁盘名称
2015-07-10 Android 高仿微信实时聊天 基于百度云推送
2015-07-10 Android添加横线和竖线分割界面
2015-07-10 ViewPager + Fragment实现滑动标签页
2015-07-10 fragment中嵌套viewpager,vierpager中有多个fragment,不显示 .