Android UI术与道

AndroidUI初探②RecyclerView.Adapter

2017-02-15  本文已影响92人  逝我

前言

早期文章 , 如今搬运过来 , RecyclerView用法相信都会,这里主要介绍一下简单的封装。

不管我们是在使用早期的ListView还是使用强大的RecyclerView ,我们都需要去实现其控件的Adapter ,将数据与控件绑定起来 。不管是ListViewAdapter还是RecyclerViewAdapter ,都需要我们实现大量的方法 ,重复的去编写相同的操作 ,为了减少不必要的编码 ,就需要将Adapter的共性抽取出来 ,做成一个通用的Adapter ,以后需要实现Adapter ,只需要继承我们自己写的Adapter就OK了 。

分析

不管是我们的ListViewAdapter还是RecyclerViewAdapter ,其主要有两点 :
第一、 外界提供给我们的数据源 , 这个是变化的 。
第二、 外界提供给我们的布局文件资源(也可拓展为布局View) , 这个也是变化,需要传递的参数
另 : RecyclerView需要我们自己实现Item的各种事件
如果布局中需要Context ,也可以作为参数传入 ,创建多个构造函数

编写 :

要封装RecyclerView.Adapter,就需要搞清楚,RecyclerViewAdapter主要实现三个方法 ,onCreateViewHolderonBindViewHoldergetItemCount ,还有一个ViewHolder类 。我们来分析分析 , 这几个方法和类 。

onCreateViewHolder

主要构件RecyclerView每个Item布局对象 ,与ViewHolder关联 ,达到复用视图的效果,并传递给 onBindViewHolder ,因为我们的布局对象都是View , 所以这个地方 , 我们可以根据传递进来的资源文件infalter成一个View ,亦或是传进来的View,再与ViewHolder关联 , 此处我们就可以对外屏蔽掉了 。


    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
    {
        View view = LayoutInflater.from(parent.getContext()).inflate(mItemLayoutRes, parent,
                false);
        ViewHolder viewHolder = new ViewHolder(view);

        // 初始化Item事件监听
        initOnItemListener(viewHolder);

        return viewHolder;
    }

onBindViewHolder

主要讲数据与ViewHolder里面的控件相关联 ,因为我要实现不同RecyclerView Item的数据显示 ,所以这个地方不能写死 ,需要我们根据情况 ,将数据绑定到不同的控件上面 , 这里需要抽象方法传递出来数据 , 让继承我们的Adapter做操作


    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
    {
        Object o = mItems.get(position);
        convertView((ViewHolder) holder,o);
    }

getItemCount


    @Override
    public int getItemCount()
    {
        return mItems.size();
    }

返回我们的Item总条数

ViewHolder

将ViewHolder类抽取出来,主要是为了更加方便的进行View组件的操作,这个类 ,主要是为我们的控件复用服务 ,因为在Adapter每个Item与ViewHolder关联 ,所以在此类中 , 我们可以做一些获取控件的简便操作 。

    
        private View mConvertView;
        private SparseArray<View> mViews;
    
        public ViewHolder(View itemView)
        {
            super(itemView);
            mViews = new SparseArray<>() ;
            mConvertView = itemView ;
        }
    
        /**
         * 根据资源获取View对象
         * @param res
         * @param <T>
         * @return
         */
        public <T extends View> T getView(@IdRes int res) {
    
            View view = mViews.get(res);
            if (view == null) {
                view = mConvertView.findViewById(res) ;
                mViews.put(res,view);
            }
            return (T) view;
        }


完整Adapter代码


    /**
     * Created by Zeno on 2016/6/8.
     *
     *  简介 :
     *      抽象类的抽取 ,主要是抽取一些有共性的方法和参数 。
     *
     *  分析:
     *      不管是ListView还是RecyclerView ,主要有两个点需要实现:
     *          第一 :外界提供的数据源
     *          第二 :外界提供的布局
     *      这两个点是明确从外部传入的 ,所以首先这两个点不能固定 ,需要作为参数从外部传入
     *      如果有一些资源需要用到上下文 ,还需要传入Context
     *
     *
     */
    public abstract class SimpleBaseRecyclerAdapter extends RecyclerView.Adapter
    {
        // each item layout res
        private int mItemLayoutRes;
        // total item data set
        private List<?> mItems;
    
        private ItemClickListener mItemClickListener ;
        private ItemLongClickListnener mItemLongClickListnener ;
    
        public SimpleBaseRecyclerAdapter(@LayoutRes int mItemLayoutRes, List<?> items)
        {
            this.mItemLayoutRes = mItemLayoutRes;
            // 如果没有传入的数据 ,则自动创建一个空的集合 ,防止报空指针
            this.mItems = items ==null ? new ArrayList<>() : items;
        }
    
        @Override
        public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType)
        {
            View view = LayoutInflater.from(parent.getContext()).inflate(mItemLayoutRes, parent,
                    false);
            ViewHolder viewHolder = new ViewHolder(view);
    
            // 初始化Item事件监听
            initOnItemListener(viewHolder);
    
            return viewHolder;
        }
    
    
        @Override
        public void onBindViewHolder(RecyclerView.ViewHolder holder, int position)
        {
            Object o = mItems.get(position);
            convertView((ViewHolder) holder,o);
        }
    
        @Override
        public int getItemCount()
        {
            return mItems.size();
        }
    
        public abstract void convertView(ViewHolder viewHolder, Object itemObj) ;
    
    
        /**
         * init set item view listener
         * @param holder
         */
        private void initOnItemListener(final RecyclerView.ViewHolder holder) {
                if (mItemClickListener != null) {
                    holder.itemView.setOnClickListener(new View.OnClickListener()
                    {
                        @Override
                        public void onClick(View v)
                        {
                            Object o = mItems.get(holder.getLayoutPosition());
                            mItemClickListener.onItemClick(v,o ,holder.getLayoutPosition());
                        }
                    });
                }
    
                if (mItemLongClickListnener != null) {
                    holder.itemView.setOnLongClickListener(new View.OnLongClickListener()
                    {
                        @Override
                        public boolean onLongClick(View v)
                        {
                            Object o = mItems.get(holder.getLayoutPosition());
                            mItemLongClickListnener.onItemLongClick(v,o,holder.getLayoutPosition());
                            return true;
                        }
                    });
                }
        }
    
        /**
         * set item view click
         * @param listener
         */
        public void setOnItemClickListener(ItemClickListener listener) {
            mItemClickListener = listener ;
        }
    
        /**
         * set item view long click
         * @param listener
         */
        public void setOnItemLongClickListener(ItemLongClickListnener listener) {
            mItemLongClickListnener = listener ;
        }
    
    
        public interface ItemClickListener {
            void onItemClick(View view ,Object itemObj , int position) ;
        }
    
        public interface ItemLongClickListnener {
            void onItemLongClick(View view ,Object itemObj, int position) ;
        }
    }



完整ViewHolder代码


    /**
     * Created by Zeno on 2016/6/8.
     *
     * ViewHolder主要是做一些与控件布局有关的操作 ,所有我们可以在这边简化一下获取控件对象的代码
     */
    public class ViewHolder extends RecyclerView.ViewHolder
    {
        private View mConvertView;
        private SparseArray<View> mViews;
    
        public ViewHolder(View itemView)
        {
            super(itemView);
            mViews = new SparseArray<>() ;
            mConvertView = itemView ;
        }
    
        /**
         * 根据资源获取View对象
         * @param res
         * @param <T>
         * @return
         */
        public <T extends View> T getView(@IdRes int res) {
    
            View view = mViews.get(res);
            if (view == null) {
                view = mConvertView.findViewById(res) ;
                mViews.put(res,view);
            }
            return (T) view;
        }
    
        /**
         * 提供TextView和Button设置文本简化操作
         * @param idRes
         * @param charSequence
         * @return
         */
        public ViewHolder setText(@IdRes int idRes , CharSequence charSequence) {
            View view = getView(idRes);
            if (view instanceof TextView) {
                ((TextView)view).setText(charSequence);
            }else if (view instanceof Button) {
                ((Button)view).setText(charSequence);
            }
    
            return this ;
        }
    
        /**
         * 提供TextView和Button设置文本颜色简化操作
         * @param idRes
         * @param color
         * @return
         */
        public ViewHolder setTextColor(@IdRes int idRes , int color) {
            View view = getView(idRes);
            if (view instanceof TextView) {
                ((TextView)view).setTextColor(color);
            }else if (view instanceof Button) {
                ((Button)view).setTextColor(color);
            }
            return this ;
        }
    
    
        /**
         * 设置指定ViewId的背景颜色
         * @param idRes
         * @param color
         * @return
         */
        public ViewHolder setBackgroundColor(@IdRes int idRes , int color) {
    
            View view = getView(idRes);
            view.setBackgroundColor(color);
    
            return this;
        }
    
        /**
         * 设置ImageView显示图片
         * @param idRes
         * @param res
         * @return
         */
        public ViewHolder setImageResoruce(@IdRes int idRes , @DrawableRes int res) {
            View view = getView(idRes);
            if (view instanceof ImageView) {
                ((ImageView)view).setImageResource(res);
            }
    
            return this ;
        }
    
        /**
         * 设置指定控件ID的点击事件
         * @param idRes
         * @param listener
         * @return
         */
        public ViewHolder setOnClickListener(@IdRes int idRes , View.OnClickListener listener) {
    
            View view = getView(idRes);
            view.setOnClickListener(listener);
    
            return this;
        }
    
        /**
         * 设置指定控件ID的长按事件
         * @param idRes
         * @param listener
         * @return
         */
        public ViewHolder setOnLongClickListener(@IdRes int idRes , View.OnLongClickListener listener) {
            View view = getView(idRes);
            view.setOnLongClickListener(listener);
    
            return this;
        }
    
        /**
         * 设置指定控件的TAG
         * @param idRes
         * @param tag
         * @return
         */
        public ViewHolder setTag(@IdRes int idRes , Object tag) {
            View view = getView(idRes);
            view.setTag(tag);
    
            return this;
        }
    
        /**
         * 获取指定控件的TAG
         * @param idRes
         * @return
         */
        public Object getTag(@IdRes int idRes) {
            View view = getView(idRes);
            return  view.getTag() ;
        }
    
    }


上一篇下一篇

猜你喜欢

热点阅读