阅读自:Android 复杂的列表视图新写法 MultiType


1、实现线性布局和网格布局混排列表 的讲解
效果图
为了实现如上图的线性和网格的混合视图效果,只需要一个 GridLayoutManager(其继承自 LinearLayoutManager)而关键的代码就是下图中的为 GridLayoutManager 设置 GridLayoutManager.SpanSizeLookup 监听器:

GridLayoutManager.SpanSizeLookupgetSpanSize() 方法返回的就是当前 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 中各种类型元素的添加顺序。

更多相关文章

  1. 浅谈Java中Collections.sort对List排序的两种方法
  2. python list.sort()根据多个关键字排序的方法实现
  3. 基于RTP和Android的视频传输的研究实现方法
  4. 使用NanoHttpd在Android上实现HttpServer
  5. Android中用Application类实现全局变量
  6. android 类似QQ 换皮肤 实现思路 apk资源共享
  7. Android(安卓)中.aar文件生成方法与用法
  8. Android(安卓)AES加密算法及其实现
  9. Android(安卓)DatePickerDialog 只显示年月

随机推荐

  1. 如何设计一款AndroidAPP
  2. android每日一问【2011-09-19】
  3. Android(安卓)ListView长按弹出对话框
  4. Android(安卓)混淆配置文件及常用第三方
  5. [android]android自动化测试十二之代码控
  6. 运行时权限解析以及申请的实现(可完美解决
  7. android 获取外置sd卡根目录
  8. Android 的res/values/colors自定义颜色
  9. Android实现页面悬浮显示
  10. Android中的style和theme的用法