RecyclerView的万能适配器+定义可以到底部自动刷新的RecyclerView

摘要:
我不会重复RecyclerView的重要性。为了方便以后直接使用,我写了这篇文章,主要包括:通用适配器在使用时分为定义布局和绑定数据,方便直接应用。添加了底部刷新,需要与我们自己编写的RecyclerView一起使用。对于布局中的每个子布局和控件,它可以响应各种单击事件:首先提取ViewHolder:这里的关键点是使用SparseArray(类似于源代码中的ArrayList)。

RecyclerView的重要性就不做重复说明了,为了方便以后直接使用写了这个,主要有:

  万能适配器在使用的时候分为定义布局和绑定数据,方便直接套用。加入了底部刷新,需要配合自己写的RecyclerView一起使用,对于布局中各个子布局和控件可以做到响应各种点击事件:

    首先抽取ViewHolder:这里的要点是用到了SparseArray(源码中类似ArrayList。直接使用Object数组进行实现):

    

package com.fightzhao.baseadapterdemo.base;

import android.content.Context;
import android.graphics.drawable.AnimationDrawable;
import android.support.v7.widget.RecyclerView;
import android.util.SparseArray;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;

/**
 * Created by fightzhao on 16/5/10.
 */
public class BaseRecyclerViewHolder extends RecyclerView.ViewHolder {
    //集合类,layout里包含的View,以view的id作为key,value是view对象()
    protected SparseArray<View> mViews;
    protected Context mContext;

    public BaseRecyclerViewHolder(Context context, View itemView) {
        super(itemView);
        mContext = context;
        mViews = new SparseArray<View>();
    }

    private <T extends View> T findViewById(int viewId) {
        View view = mViews.get(viewId);
        if (view == null) {
            view = itemView.findViewById(viewId);
            mViews.put(viewId, view);
        }
        return (T) view;
    }

    public View getView(int viewId) {
        return findViewById(viewId);
    }

    public TextView getTextView(int viewId) {
        return (TextView) getView(viewId);
    }

    public Button getButton(int viewId) {
        return (Button) getView(viewId);
    }

    public ImageView getImageView(int viewId) {
        return (ImageView) getView(viewId);
    }

    public ImageButton getImageButton(int viewId) {
        return (ImageButton) getView(viewId);
    }

    public EditText getEditText(int viewId) {
        return (EditText) getView(viewId);
    }

    /**
     * 实现底部转圈圈的效果,这里可以定制的,比如使用吃豆人的效果
     * @param viewId
     * @return
     */
    public AnimationDrawable getAnimationDrawable(int viewId) {
        return (AnimationDrawable) getView(viewId).getBackground();
    }

    public BaseRecyclerViewHolder setText(int viewId, String value) {
        TextView view = findViewById(viewId);
        view.setText(value);
        return this;
    }

    public BaseRecyclerViewHolder setBackground(int viewId, int resId) {
        View view = findViewById(viewId);
        view.setBackgroundResource(resId);
        return this;
    }

    public BaseRecyclerViewHolder setClickListener(int viewId, View.OnClickListener listener) {
        View view = findViewById(viewId);
        view.setOnClickListener(listener);
        return this;
    }

}

  

BaseAdapter代码:

package com.fightzhao.baseadapterdemo.base;

import android.content.Context;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.StaggeredGridLayoutManager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;

import com.fightzhao.baseadapterdemo.R;
import com.fightzhao.baseadapterdemo.callback.OnItemClickListener;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by fightzhao on 16/5/10.
 * RecyclerView通用适配器
 */
public abstract class BaseRecyclerAdapter<T> extends RecyclerView.Adapter<BaseRecyclerViewHolder> {
    /**
     * RecyclerView的加载样式
     * 当滑动到底部时候的加载
     */
    public static final int TYPE_HEADER = 1;
    public static final int TYPE_ITEM = 2;
    public static final int TYPE_FOOTER = 3;

    protected List<T> mData;
    protected Context mContext;
    protected LayoutInflater mInflater;
    protected OnItemClickListener mClickListener;
    private RecyclerView.LayoutManager mLayoutManager;

    protected boolean mUseAnimation;
    protected boolean mShowFooter;

    private int mLastPosition = -1;

    /**
     * 瀑布流
     *
     * @param savedInstanceState
     */
    private List<Integer> mHeights;

    public BaseRecyclerAdapter(Context context, List<T> data) {
        this(context, data, true);
    }

    public BaseRecyclerAdapter(Context context, List<T> data, boolean useAnimation) {
        this(context, data, useAnimation, null);
    }

    public BaseRecyclerAdapter(Context context, List<T> data, boolean useAnimation, RecyclerView.LayoutManager layoutManager) {
        mContext = context;
        mUseAnimation = useAnimation;
        mLayoutManager = layoutManager;
        mData = data == null ? new ArrayList<T>() : data;
        mInflater = LayoutInflater.from(context);

        mHeights = new ArrayList<Integer>();
        for (int i = 0; i < mData.size(); i++) {
            mHeights.add((int) (100 + Math.random() * 300));
        }

    }

    public void setOnItemClickListener(OnItemClickListener listener) {
        mClickListener = listener;
    }

    @Override
    public BaseRecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == TYPE_FOOTER) {
            // 底部加载更多的样式
            return new BaseRecyclerViewHolder(mContext, mInflater.inflate(R.layout.item_load_more, parent, false));
        } else {
            // 正常情况下的布局样式和点击事件(以接口的形式向外提供)
            final BaseRecyclerViewHolder holder = new BaseRecyclerViewHolder(mContext,
                    mInflater.inflate(getItemLayoutId(viewType), parent, false));
            if (mClickListener != null) {

                /**
                 * 点击事件
                 */
                holder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        mClickListener.onItemClick(v, holder.getLayoutPosition());
                    }
                });

                holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                    @Override
                    public boolean onLongClick(View v) {
                        mClickListener.onItemLongClick(v, holder.getLayoutPosition());
                        return false;
                    }
                });

                holder.getTextView(R.id.tv_title).setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        mClickListener.onTextViewClick(v, holder.getLayoutPosition());
                    }
                });
            }
            return holder;
        }
    }

    @Override
    public void onBindViewHolder(BaseRecyclerViewHolder holder, int position) {
        if (getItemViewType(position) == TYPE_FOOTER) {
            if (mLayoutManager != null) {
                if (mLayoutManager instanceof StaggeredGridLayoutManager) {
                    if (((StaggeredGridLayoutManager) mLayoutManager).getSpanCount() != 1) {
                        StaggeredGridLayoutManager.LayoutParams params = (StaggeredGridLayoutManager.LayoutParams) holder.itemView
                                .getLayoutParams();
                        params.setFullSpan(true);

                    } else if (mLayoutManager instanceof GridLayoutManager) {
                        if (((GridLayoutManager) mLayoutManager)
                                .getSpanCount() != 1 && ((GridLayoutManager) mLayoutManager)
                                .getSpanSizeLookup() instanceof GridLayoutManager.DefaultSpanSizeLookup) {
                            throw new RuntimeException("网格布局列数大于1时应该继承SpanSizeLookup时处理底部加载时布局占满一行。");
                        }
                    }
                }
            }

            // 底部加载的处理
            holder.getImageView(R.id.loading_icon).setVisibility(View.VISIBLE);
            holder.getAnimationDrawable(R.id.loading_icon).start();
        } else {
            // 布局样式处理完毕后,处理数据
            bindData(holder, position, mData.get(position));
            if (mUseAnimation) {
                setAnimation(holder.itemView, position);
            }

        }


    }

    @Override
    public int getItemCount() {
        int i = mShowFooter ? 1 : 0;
        return mData != null ? mData.size() + i : 0;
    }

    /**
     * Item的样式布局Id
     *
     * @param viewType
     * @return
     */
    public abstract int getItemLayoutId(int viewType);

    @Override
    public int getItemViewType(int position) {
        if (mShowFooter && getItemCount() - 1 == position) {
            return TYPE_FOOTER;
        }
        return bindViewType(position);
    }

    protected int bindViewType(int position) {
        return 0;
    }

    /**
     * 绑定数据
     *
     * @param holder
     * @param position
     * @param item
     */
    public abstract void bindData(BaseRecyclerViewHolder holder, int position, T item);

    /**
     * 动画的处理
     *
     * @param viewToAnimate
     * @param position
     */
    protected void setAnimation(View viewToAnimate, int position) {
        if (position > mLastPosition) {
            Animation animation = AnimationUtils
                    .loadAnimation(viewToAnimate.getContext(), R.anim.item_bottom_in);
            viewToAnimate.startAnimation(animation);
            mLastPosition = position;
        }
    }

    /**
     * Adapter显示尾部
     */
    public void showFooter() {
        notifyItemInserted(getItemCount());
        mShowFooter = true;
    }

    /**
     * Adapter隐藏尾部
     */
    public void hideFooter() {
        notifyItemRemoved(getItemCount() - 1);
        mShowFooter = false;
    }

    public void setData(List<T> data) {
        mData = data;
        notifyDataSetChanged();
    }

    public void add(int pos, T item) {
        mData.add(pos, item);
        notifyItemInserted(pos);
    }

    public void delete(int pos) {
        mData.remove(pos);
        notifyItemRemoved(pos);
    }

    public void addMoreData(List<T> data) {
        int startPos = mData.size();
        mData.addAll(data);
        notifyItemRangeInserted(startPos, data.size());
    }

    public List<T> getData() {
        return mData;
    }
}

  

    

免责声明:文章转载自《RecyclerView的万能适配器+定义可以到底部自动刷新的RecyclerView》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇delphi 文件的操作【STM32H7】第6章 ThreadX操作系统移植(IAR)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

div固定显示的几种方法

很多时候我们会受到一些需求: 1、div一直置顶 2、div一直置底 3、超过一定的位置之后div置顶 4、超过一定位置之后div置底 那么下面针对上面的几个问题写几个案例: 一、div一直在屏幕的上方,这个倒是容易咱们直接使用position:fixed;然后设置他的top值和left就可以了,别忘了设置宽度哦 <div class="top"&g...

全国城市部分js

var areaJson22 = { "id": "0", "name": "全国", "parentId": null, "checked": false, "isParent": "true", "icon": null,...

CSS定位

css定位css有三种基本的定位机制:普通流,浮动和绝对定位。css中position属性static,relative,absolute,fixed      position:relative相对定位会按照元素的原始位置对该元素进行移动      position:absolute绝对定位,元素可以放置到页面上的任何位置,后面加上left,top等值 ...

元素大小-偏移量(offset)客户区大小(client)滚动大小(scroll)

一、偏移量---offset 1、定位父级   在理解偏移大小之前,首先要理解offsetParent。人们并没有把offsetParent翻译为偏移父级,而是翻译成定位父级,很大原因是offsetParent与定位有关   定位父级offsetParent的定义------》与当前元素最近的经过定位(position不等于static)的父级元素,主要...

unity Mathf 数学运算汇总

在使用unity做游戏的过程中难免会遇到这样那样的数学运算,比如简单的正弦,余弦等。其实,在c#的Mathf 函数中 还有很多方便我们开发使用的 数学函数。在此,分享下比较全面的Mathf解析(由网上收集),方便大家参考 使用。 Mathf 数学运算 Mathf.Abs绝对值 计算并返回指定参数 f 绝对值。 Mathf.Acos反余弦 static fu...

前端开发中常遇到的浏览器兼容问题小结

1. 默认的内外边距不同 问题:各个浏览器默认的内外边距不同 解决:*{margin:0;padding:0;} 2. 水平居中的问题 问题:设置 text-align: center;  ie6-7文本居中,嵌套的块元素也会居中,ff /opera /safari /ie8文本会居中,嵌套块不会居中 解决:块元素设置 1、margin-left:auto...