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

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;
    }
}

  

    

时间: 2024-08-07 08:55:41

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

打造android偷懒神器———RecyclerView的万能适配器

转载请注明出处谢谢:http://www.cnblogs.com/liushilin/p/5720926.html 很不好意思让大家久等了,本来昨天就应该写这个的,无奈公司昨天任务比较紧,所以没能按时给大家带来RecyclerView的适配器,楼主对期待的小伙伴表示最深刻地歉意. 如果你没有看前面的万能的ListView,GridView等的万能适配器,楼主推荐你去看一看,当然,大牛就免了. 另外,楼主今天在构思这个RecyclerView的过程中发现前天写的ListView有点毛病,现在楼主已

Android搜索结果显示高亮(有数据滑动底部自动刷新)

首先的效果图 搜索到结果(这里我只是模拟数据,真正和服务器走得时候,返回来的数据都应该包含关键字的) 模拟的没有搜索结果的界面 具体实现 在这插一句哈,就是做一件事情,拆分成多个小结,不至于在开发的时候摸不着头脑而且还能把控开发的进度. 思路其实很简单,我们监听输入框的变化,然后在文字变化之后去请求服务器,然后取到我们需要的结果,进行数据展示即可. 第一步:搜索框的监听 et_search.addTextChangedListener(new TextWatcher() { @Override

RecyclerView万能适配器

转载请申明:http://blog.csdn.net/yoyo_newbie/article/details/48130813 没次当我们用RecyclerView是时候,不得不想到要添加点击事件, 头部,尾部,甚至分组繁琐代码烦恼,于是本人就无奈写了共用的adapter. 使用说明: 如,item资源为 R.layout.fragment_jiongtu_item_of_indexfregment item里面有个imageview id为 R.id.iv_photo private clas

RecyclerView的通用适配器

本来这一个主题应该早就写了,只是项目多,属于自己的时间不多,所以现在才开动!! 前一段时间写了一篇文章,是关于ListView,GriView万能适配器,没有看过的同学,可以先看看那篇文章,然后在来学习RecyclerView的话,会容易很多.链接http://www.cnblogs.com/huangjialin/p/7661328.html 当然,如果对RecyclerView基础不是了解的朋友,建议先去熟悉一下RecyclerView的基础知识! 闲话不多说,先简单的介绍一下这个Recyc

Android进阶笔记10:Android 万能适配器

1. Android 万能适配器      项目中Listview GridView几乎是必用的组件,Android也提供一套机制,为这些控件绑定数据,那就是Adapter.用起来虽然还不错,但每次都需要去继承一个BaseAdapter,然后实现里面的一大堆方法,而我们每次最关心的无非就是getView方法,其余的方法几乎都是相同代码.这里是不是就可以优化起来呢?在其次,我们在使用Adapter的时候,为了优化性能,常常会创建一个Holder.而Holder里面每次存放的都是View,对Hole

万能适配器的一些问题

不用万能适配器volley都能搞定如果用万能适配器则不能用volley(因为万能适配器里边有自己的settag)可以用NUtils在 NUtils里边自定义三级缓存每次设图片时都去访问三级缓存 1 package com.example.wannengadapter; 2 3 import java.util.List; 4 5 import android.content.Context; 6 import android.view.LayoutInflater; 7 import andro

让偷懒更彻底——用Butterknife 来为recyclerview 打造通用适配器(上)

背景 随着recyclerview 的越来越普及,其高度的易用性,让我们越来越爱不释手,当然网上也出现了很多类似的通用适配器,让我们更加方便的使用它,今天我们这里介绍一种新的recyclerview的通用适配器的实现思路--把recyclerview和ButterKnife结合起来使用(ps:因为公司开发一直使用butterknife,才有了这种想法). 首先贴上我的实现效果: 代码用法使用: ModelRecyclerAdapter adapter = new ModelRecyclerAda

Android开发之万能适配器

ListView.GridView等等非常多的东西都需要适配器.而如果开发一个app每一个listview都有写一个Adapter的话,那还怎么愉快的玩游戏.. 什么是ViewHolider以及的用法和为什么要用? 这位博主写的非常好. http://www.cnblogs.com/lichenwei/p/4085107.html 所谓的万能适配器,无非是将适配器的重复代码抽取出来进行封装.不同功能的代码则留写一个方法留给用户复写,则每个listview的适配器就只变成几句话就够了. 这是一般适

慕课网 万能适配器学习笔记

首先再次感谢 慕课网的技术大牛分享了该课程. 一.传统 ListView 适配器的模式:1. 创建Listview,并为listview 创建item布局2.封装数据 3.为Item布局创建特定的适配器 用于数据展示.(在这过程中,如果某一个ListView 的item中控件过多,控件的生命及调用会导致代码量上升,而如果一个app中有很多个地方需要用到ListView 时,需要分别写多个适配器,会导致很多重复性的操作,为了避免这种情况的发生,让编码更轻松,可参考 慕课网Android万能适配器