《Android 复杂的列表视图新写法 MultiType》知识点整理

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


1、实现线性布局和网格布局混排列表 的讲解
《Android 复杂的列表视图新写法 MultiType》知识点整理_第1张图片 效果图
为了实现如上图的线性和网格的混合视图效果,只需要一个 GridLayoutManager(其继承自 LinearLayoutManager)而关键的代码就是下图中的为 GridLayoutManager 设置 GridLayoutManager.SpanSizeLookup 监听器:
《Android 复杂的列表视图新写法 MultiType》知识点整理_第2张图片
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));

效果图:
《Android 复杂的列表视图新写法 MultiType》知识点整理_第3张图片
根据以上总结,要分别定义两组 JavaBean 与 ItemViewBinder以及对应的 Item Layout。


补充

1、在使用 MultiType 的时候,不可避免的要根据需求实现对应的 JavaBean 与 ItemViewBinder,以及对应的 Item Lauout,有时候就让人觉得麻烦,因为每一种 Item 都要实现对应的 JavaBean 与 ItemViewBinder,在项目层次上也会多了需要的 Java 类,为了缓解这种情况, Multitype 有实现 一个类型对应多个 ItemViewBinder,来减少 JavaBean 类型的书写。

而在有些情况下,也可以为 JavaBean 对应一个基类,然后在继承该基类实现具体的逻辑,而在使用 adapter.register() 进行类型注册的时候,就可以实现多个子类对应一个 ItemViewBinder,然后在 onBindViewHolder 中根据传入的实例的具体子类型再做判断,修改布局的样式等。就比如下面的效果:
《Android 复杂的列表视图新写法 MultiType》知识点整理_第4张图片
先定义 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 中各种类型元素的添加顺序。

你可能感兴趣的:(Android附加技能,Android好文收藏)