《Android(安卓)复杂的列表视图新写法 MultiType》知识点整理
阅读自:Android 复杂的列表视图新写法 MultiType
1、实现线性布局和网格布局混排列表 的讲解
效果图
为了实现如上图的线性和网格的混合视图效果,只需要一个 GridLayoutManager
(其继承自 LinearLayoutManager
)而关键的代码就是下图中的为 GridLayoutManager
设置 GridLayoutManager.SpanSizeLookup
监听器: GridLayoutManager.SpanSizeLookup
的 getSpanSize()
方法返回的就是当前 position
位置的 item 所占的网格数。在这里,当 Item 对应为 特别篇\本篇
一栏时,因为效果上该栏需要占一整行,所以当判定为该栏时,就返回 5 ,表示该栏需要占 5 个网格的宽度。,而每一行总共 5 个网格,即会占满整行。
2、实现 RecyclerView 嵌套横向 RecyclerView
如果是要实现竖向的 RV 里面嵌套一个横向的 RV ,则只需要把横向的 RV 当作一个特殊的 Item 即可,实现起来主要有以下几个步骤:
(1)首先定义横向的 RV 的 Item 的布局文件,假设名为 item_hor_list_item.xml
,且内部就是一个简单的 TextView
;
(2)然后定义横向RV 的 Item 对应的 JavaBean,这里为了节省代码,直接使用现成的 String
对象;
(3)然后是定义对应的 ItemViewBinder
,名为 ItemHorListBeanBinder.java
:
public class ItemHorListBeanBinder extends ItemViewBinder<String,ItemHorListBeanBinder.ViewHolder>{ @NonNull @Override protected ViewHolder onCreateViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) { return new ViewHolder(inflater.inflate(R.layout.item_hor_list_item, parent, false)); } @Override protected void onBindViewHolder(@NonNull ViewHolder holder, @NonNull String item) { holder.textView.setText(item); } static class ViewHolder extends RecyclerView.ViewHolder { public TextView textView; public ViewHolder(View itemView) { super(itemView); textView = (TextView) itemView; } }}
(4)接着就要为竖向的 RV 中那个特殊的 Item(即对应横向 RV 的)定义布局文件,名为 item_hor_rv_layout.xml
,里面就一个独立的 RV:
.support.v7.widget.RecyclerView xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="50dp">.support.v7.widget.RecyclerView>
(5)然后上述的特殊的 Item 定义对应的 JavaBean,名为:HorListBean.java
:
public class HorListBean { // 用来存放横向 RV 的 Item 数据 private List<String> data; public HorListBean(List<String> data) { this.data = data; } public List<String> getData() { return data; } public void setData(List<String> data) { this.data = data; }}
这里只是简单的实现,如原文中的,还可以用一个成员变量记录横向 RV 的滑动到某一处的位置,用于在竖向的 RV 的 Item 因上下滑动刷新之后能使横向的 RV 能够恢复到原来的滑动的位置,使逻辑更加的完善。
(6)然后定义对应的 ItemViewBinder
,名为 HorListBinder.java
:
public class HorListBinder extends ItemViewBinder<HorListBean, HorListBinder.ViewHolder> { @NonNull @Override protected ViewHolder onCreateViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) { return new ViewHolder(inflater.inflate(R.layout.item_hor_rv_layout, parent, false)); } @Override protected void onBindViewHolder(@NonNull ViewHolder holder, @NonNull HorListBean item) { Items items = new Items(); List list = item.getData(); for (String s : list) { items.add(s); } holder.setData(items); } static class ViewHolder extends RecyclerView.ViewHolder { private RecyclerView recyclerView; private MultiTypeAdapter adapter; public ViewHolder(View itemView) { super(itemView); recyclerView = (RecyclerView) itemView; adapter = new MultiTypeAdapter(); adapter.register(String.class, new ItemHorListBeanBinder()); LinearLayoutManager manager = new LinearLayoutManager(itemView.getContext()); //设置为横向的 manager.setOrientation(LinearLayoutManager.HORIZONTAL); recyclerView.setLayoutManager(manager); recyclerView.setAdapter(adapter); } public void setData(Items items) { adapter.setItems(items); adapter.notifyDataSetChanged(); } }}
在 ViewHolder
中完成对横向 RV 的相关初始化。
(7)最后就只需要为竖向的 RV 对应的 MultiTypeAdapter
实例进行类型注册 :
adapter.register(HorListBean.class, new HorListBinder());
然后为其对应的 Items 添加 HorListBean
实例即可:
items.add(new HorListBean(list));
效果图:
根据以上总结,要分别定义两组 JavaBean 与 ItemViewBinder以及对应的 Item Layout。
补充
1、在使用 MultiType 的时候,不可避免的要根据需求实现对应的 JavaBean 与 ItemViewBinder,以及对应的 Item Lauout,有时候就让人觉得麻烦,因为每一种 Item 都要实现对应的 JavaBean 与 ItemViewBinder,在项目层次上也会多了需要的 Java 类,为了缓解这种情况, Multitype 有实现 一个类型对应多个 ItemViewBinder
,来减少 JavaBean 类型的书写。
而在有些情况下,也可以为 JavaBean 对应一个基类,然后在继承该基类实现具体的逻辑,而在使用 adapter.register()
进行类型注册的时候,就可以实现多个子类对应一个 ItemViewBinder,然后在 onBindViewHolder
中根据传入的实例的具体子类型再做判断,修改布局的样式等。就比如下面的效果:
先定义 JavaBean 基类:
public class TextViewBean { protected String text; public TextViewBean(String text) { this.text = text; } public String getText() { return text; } public void setText(String text) { this.text = text; }}
然后实现具体的子类 Post :
public class Post extends TextViewBean { public List comments; public Post(String text) { super(text); }}
和 Comment:
public class Comment extends TextViewBean{ public Comment(String text) { super(text); }}
然后是公共的 ItemViewBinder:
public class TextViewBinder extends ItemViewBinder<TextViewBean,TextViewBinder.ViewHoler> { @NonNull @Override protected ViewHoler onCreateViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) { // 对应的布局文件里面就是一个单独的 TextView View view = inflater.inflate(R.layout.item_text_layout, parent, false); return new ViewHoler(view); } @Override protected void onBindViewHolder(@NonNull ViewHoler holder, @NonNull TextViewBean item) { holder.textView.setText(item.getText()); Resources resources= holder.textView.getContext().getResources(); // 根据 item 的具体类型动态的变换 TextView 样式 if (item instanceof Post) { holder.textView.setGravity(Gravity.LEFT); holder.textView.setBackgroundColor(resources.getColor(R.color.colorAccent)); } else { holder.textView.setGravity(Gravity.RIGHT); holder.textView.setBackgroundColor(resources.getColor(R.color.colorPrimary)); } holder.textView.setTextColor(resources.getColor(R.color.white)); holder.textView.setTextSize(20); } static class ViewHoler extends RecyclerView.ViewHolder{ @NonNull final TextView textView; public ViewHoler(View itemView) { super(itemView); textView= (TextView) itemView; } }}
然后分别注册就行了:
adapter.register(Post.class, new TextViewBinder());adapter.register(Comment.class, new TextViewBinder());
2、还有一个点需要注意,就是复杂样式的排版布局顺序,依赖于 Items 中各种类型元素的添加顺序。
更多相关文章
- 浅谈Java中Collections.sort对List排序的两种方法
- python list.sort()根据多个关键字排序的方法实现
- 基于RTP和Android的视频传输的研究实现方法
- 使用NanoHttpd在Android上实现HttpServer
- Android中用Application类实现全局变量
- android 类似QQ 换皮肤 实现思路 apk资源共享
- Android(安卓)中.aar文件生成方法与用法
- Android(安卓)AES加密算法及其实现
- Android(安卓)DatePickerDialog 只显示年月