Android RecyclerView与泛型 简单实现多布局

本文介绍了Android的RecyclerView控件,它结合了ListView和GridView的功能,并重点讲解如何利用泛型实现多布局。内容包括RecyclerView的基本概念、依赖引入、关键类如Adapter、LayoutManager的介绍,以及实现多布局的主要步骤,包括适配器封装、ViewHolder、布局监听等。最后提供了相关代码示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

RecyclerView简介:

谷歌在support v7中,加入了新的控件——RecyclerView,该控件整合了ListView、GridView的特点,而且最大的优点是可以很方便实现瀑布流效果,多布局控制效果等等,因此RecyclerView受到越来越多的开发者重视。

引入RecyclerView

由于该控件并不在Andorid SDK中的,而是在support v7包中,因此我们要手动添加该控件。
在build.gradle中添加如下依赖:

dependencies {   
  ...
  compile 'com.android.support:appcompat-v7:23.1.1'  //Toolbar
  compile 'com.android.support:recyclerview-v7:23.1.1' //RecyclerView
}

几个重要的类:

  1. RecyclerView.Adapter:抽象类,为RecyclerView提供数据,一般根据不同的业务需求来编写具体的实现类。
  2. RecyclerView.LayoutManager:抽象类,主要用于测量RecyclerView的子Item,以及根据不同的布局方式来实现Item的布局效果,v7包自带的实现类有:LinearLayoutManager、StaggeredGridLayoutManager、GridLayoutManager。
  3. RecyclerView.ItemDecoration:抽象类,这个主要用于不同的Item之间添加分割线(可选)。官方没有实现类,所以如果要添加分割线,我们需要手动实现这个抽象类。
  4. RecyclerView.ItemAnimator:抽象类,这个主要用于当一个item添加或者删除的时候出现的动画效果,官方提供一个默认的实现类。如果想要使我们的RecyclerView在添加、删除数据的时候有炫酷的动画,可以实现这个抽象类。

使用RecyclerView的主要步骤:

  1. 引入RecyclerView
  2. 添加XML布局
  3. 封装Adapter适配器
  4. 封装RecyclerView.ViewHolder类
  5. 实现多布局展示
  6. 各布局控件监听

注:在此主要实现三种不同布局加载,RecyclerView监听及子布局监听

MyAdapter类代码

package com.example.administrator.foundationdemo.recyclerview;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;

import com.example.administrator.foundationdemo.R;

import java.util.List;

/**
 * Created by "sinlov" on 2017/4/12.
 */
public abstract class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
   
   

    private int mLayoutId;
    private Context mContext;
    private List<Data> mDataSet;

    /**
     * 构造器,接受数据集
     * @param data
     */
    public MyAdapter(Context context,List<Data> data){
        mContext = context;
        mDataSet = data;
    }

    /**
     * onCreateViewHolder:创建ViewHolder,
     * 该方法会在RecyclerView需要展示一个item的时候回调。
     * 重写该方法时,应该使ViewHolder加载item view的布局。
     * 这个能发避免了不必要的findViewById操作,提高了性能。
     *
     * @param parent
     * @param viewType
     * @return
     */
    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //加载布局文件
        switch (viewType){
            case ViewItems.TEMPLATE_1:
                break;
            case ViewItems.TEMPLATE_2:
                mLayoutId = R.layout.activity_recycler_view_recyclerview_item_my;

                break;
            case ViewItems.TEMPLATE_3:

                break;
            case ViewItems.TEMPLATE_4:
                break;
            case ViewItems.TEMPLATE_5:
                mLayoutId = R.layout.activity_recycler_view_recyclerview_item_ordinary_notification_1;
                break;
            case ViewItems.TEMPLATE_6:
                mLayoutId = R.layout.activity_recycler_view_recyclerview_item_ordinary_notification_2;
                break;
        }
        MyViewHolder holder = MyViewHolder.get(mContext,null,parent,mLayoutId);
        setListener(parent, holder);
        return holder;
    }

    /**
     * onBindeViewHolder:该方法在RecyclerView在特定位置展示数据时候回调,顾名思义,把数据绑定、填充到相应的item view中
     *
     * @param holder
     * @param position
     */
    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        //将数据填充到具体的view中
        convert(holder,mDataSet.get(position));
    }

    public abstract void convert(MyViewHolder holder, Data t);

    /**
     * 通过重写getItemViewType(int position)方法来告诉onCreateViewHolder(...)每个条目对应的布局
     * @param position
     * @return
     */
    @Override
    public int getItemViewType(int position) {
        return mDataSet.get(position).getViewType();
    }


    /**
     * getItemCount:返回数据的数量
     * @return
     */
    @Override
    public int getItemCount() {
        return mDataSet.size();
    }


    /**
     * java回调机制,依赖于子Item View的onClickListener及onLongClickListener。
     * @param <T> //数据类
     */
    public interface OnItemClickListener<T>{
        //RecyclerView监听
        void onItemClick(ViewGroup parent, View view, T t, int position);
    }
    public interface OnItemLongClickListener<T>{
        //长按监听
        boolean onItemLongClick(ViewGroup parent, View view, T t, int position);
    }

    private OnItemClickListener mOnItemClickListener;
    private OnItemLongClickListener mOnItemLongClickListener;

    public void setOnItemClickListener(OnItemClickListener mOnItemClickListener){
        this.mOnItemClickListener = mOnItemClickListener;
    }

    public void setOnItemLongClickListener(OnItemLongClickListener mOnItemLongClickListener) {
        this.mOnItemLongClickListener = mOnItemLongClickListener;
    }

    protected void setListener(final ViewGroup parent, final MyViewHolder holder){
        //判断是否设置了监听器
        if(mOnItemClickListener != null) {
            //为ItemView设置监听器
            holder.getConvertView().setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    int position = holder.getLayoutPosition();
                    mOnItemClickListener.onItemClick(parent, v, mDataSet.get(position), position);
                }
            });
        }
        if(mOnItemLongClickListener != null){
            holder.getConvertView().setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    if (mOnItemLongClickListener != null) {
                        int position = holder.getLayoutPosition();
                        return mOnItemLongClickListener.onItemLongClick(parent, v, mDataSet.get(position), position);
                        //返回true 表示消耗了事件 事件不会继续传递
                    }

                    return false;
                }
            });
        }
    }
}

MyViewHolder类代码:

package com.example.administrator.foundationdemo.recyclerview;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

/**
 * Created by "sinlov" on 2017/4/13.
 */
public class MyViewHolder extends RecyclerView.ViewHolder {
   
   


    private SparseArray<View> mViews;
    private View mConvertView;
    private Context mContext;
    private int mLayoutId;

    public MyViewHolder(Context context, View itemView, ViewGroup parent) {
        super(itemView);
        //由于itemView是item的布局文件,我们需要的是里面的textView,因此利用itemView.findViewById获
        //取里面的View实例,后面通过onBindViewHolder方法能直接填充数据到每一个View了
        mContext = context;
        mConvertView = itemView;
        //运用泛型,适配所有的View,多布局,不用写多个RecyclerView.ViewHolder。
        mViews = new SparseArray<View>();
        mConvertView.setTag(this);

    }

    //缓存
    public static MyViewHolder get(Context context, View convertView,
                                 ViewGroup parent, int layoutId){

        if(null==convertView){
            View itemView = LayoutInflater.from(context).inflate(layoutId, parent, false);
            MyViewHolder holder = new M
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值