RecycleView使用(一)

Android 2016-04-04

RecyclerView架构,高度的解耦,异常的灵活.通过设置它提供的不同LayoutManager,ItemDecoration , ItemAnimator实现令人瞠目的效果。

起步

  • 控制其显示方式,通过布局管理器LayoutManager
  • 控制Item间的间隔(可绘制),通过ItemDecoration
  • 控制Item增删的动画,通过ItemAnimator
  • 控制点击、长按事件,得自己通过接口回调的方式进行

    Android Studio配置

    在build.gradle中的dependencies添加

    compile 'com.android.support:recyclerview-v7:22.2.1'

布局文件

<!--侧边栏内容-->
    <android.support.v7.widget.RecyclerView
        android:id="@+id/RecyclerView"
        android:layout_width="280dp"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:background="#ffffff"
        android:scrollbars="vertical">

    </android.support.v7.widget.RecyclerView>

创建ViewHolder

可以自己创建一个ViewHolder类,继承 RecyclerView.ViewHolder

public static class ViewHolder extends RecyclerView.ViewHolder {
        int HolderId;

        private ImageView mAvatar;
        private ImageView mItemIcon;
        private TextView mItemText;
        private TextView releaseTask;
        private TextView getTask;
        private TextView finishTask;
        public ViewHolder(View itemView, int ViewType) {
            super(itemView);
            if (ViewType == NavAdapter.TYPE_ITEM) {
                mItemText = (TextView)itemView.findViewById(R.id.nav_text);
                mItemIcon = (ImageView)itemView.findViewById(R.id.nav_icon);
                HolderId = 1;
            } else {
                mAvatar = (CircleImageView)itemView.findViewById(R.id.header_icon);
                releaseTask = (TextView)itemView.findViewById(R.id.header_releaseTask);
                getTask = (TextView)itemView.findViewById(R.id.header_releaseTask);
                finishTask = (TextView)itemView.findViewById(R.id.header_releaseTask);
                HolderId = 0;
            }
        }
}

这样之后对布局文件中的组件就直接通过viewHolder进行访问,无需每次都findViewById。

创建 Adapter

public class NavAdapter extends RecyclerView.Adapter<NavAdapter.ViewHolder> {
    //不同的类型标志
    private static final int TYPE_HEADER = 0;
    private static final int TYPE_ITEM = 1;
    private String[] mNavTitle;
    private Bitmap mAvatar;
    private LayoutInflater mInflater;
    private Context context;
    private int releaseTask;
    private int getTask;
    private int finishTask;
    private MainActivity activity;
    private int[] nomal_icons=null;
    private int[] selected_icon=null;
    private OnRecyclerViewItemClickListener mOnItemClickListener = null;
    /**
     * 定义接口
     */
    public static interface OnRecyclerViewItemClickListener {
        void onItemClick(View view , int position ,NavAdapter.ViewHolder viewHolder);
    }
    public void setOnItemClickListener(OnRecyclerViewItemClickListener listener) {
        this.mOnItemClickListener = listener;
    }
    public class MyClickListner implements View.OnClickListener{
        private NavAdapter.ViewHolder viewHolder;
        public MyClickListner(NavAdapter.ViewHolder viewHolder)
        {
            this.viewHolder=viewHolder;
        }
        @Override
        public void onClick(View v) {
            mOnItemClickListener.onItemClick(v,(int)v.getTag(),viewHolder);
        }
        public NavAdapter.ViewHolder getViewHolder()
        {
            return viewHolder;
        }
    }
    public NavAdapter(MainActivity activity, String[] navTitle) {
        this.context = activity.getBaseContext();
        this.mInflater = LayoutInflater.from(context);
        this.mNavTitle = navTitle;
        MyApplication myApplication=(MyApplication)activity.getApplication();
        setmAvatar(myApplication.getIcon());
        setReleaseTask(myApplication.getReleaseTask());
        setGetTask(myApplication.getGetTask());
        setFinishTask(myApplication.getFinishTask());
        nomal_icons=new int[]{R.drawable.ic_format_list_bulleted_black,R.drawable.ic_location_black,R.drawable.ic_create_black,R.drawable.ic_my_location_black,R.drawable.ic_my_location_black
                                ,R.drawable.ic_person_black,R.drawable.ic_mail_black};
        selected_icon=new int[]{R.drawable.ic_format_list_bulleted_selected,R.drawable.ic_location_selected,R.drawable.ic_create_selected,R.drawable.ic_my_location_selected,R.drawable.ic_my_location_selected
                ,R.drawable.ic_person_selected,R.drawable.ic_mail_selected};
    }
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {
        if (holder.HolderId == 1) {
            holder.mItemText.setText(mNavTitle[position-1]);
            holder.mItemIcon.setImageResource(nomal_icons[position - 1]);
            //将数据保存在itemView的Tag中,以便点击时进行获取
            //将创建的View注册点击事件
            holder.itemView.setOnClickListener(new MyClickListner(holder));
            holder.itemView.setTag(holder.getLayoutPosition());
        } else {
            holder.mAvatar.setImageBitmap(mAvatar);
            holder.finishTask.setText(getFinishTask());
            holder.getTask.setText(getGetTask());
            holder.releaseTask.setText(getReleaseTask());
        }
    }

    @Override
    public NavAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //根据不同的类型创建不同的布局
        if (viewType == TYPE_ITEM) {
            View v = mInflater.inflate(R.layout.item_nav,parent,false);
            ViewHolder vhItem = new ViewHolder(v,viewType);
            return vhItem;
        } else if (viewType == TYPE_HEADER){
            View v = mInflater.inflate(R.layout.header, parent, false);
            ViewHolder vhHeader = new ViewHolder(v,viewType);
            return vhHeader;
        }
        return null;
    }

    @Override
    public int getItemViewType(int position) {
        //如果item为第一个就为Header类型
        if (isPositionHeader(position)) {
            return TYPE_HEADER;
        } else {
            return TYPE_ITEM;
        }
    }
    private boolean isPositionHeader(int position) {
        return position == 0;
    }

    @Override
    public int getItemCount() {
        //这里加了一个Header所有要+1
        return mNavTitle.length + 1;
    }
    @Override
    public long getItemId(int position) {
        return super.getItemId(position);
    }
}

由于RecycleView没有itemclicklistener,所以我们得自己创建一个接口,然后采用接口回调的方式进行对item的监听。

  • onCreateViewHolder() 这个方法主要生成为每个Item inflater出一个View,但是该方法返回的是一个ViewHolder。方法是把View直接封装在ViewHolder中,然后我们面向的是ViewHolder这个实例,当然这个ViewHolder需要我们自己去编写。直接省去了当初的convertView.setTag(holder)和convertView.getTag()这些繁琐的步骤。
  • onBindViewHolder() 这个方法主要用于适配渲染数据到View中。方法提供给你了一个viewHolder,而不是原来的convertView。
  • getItemCount() 得到item的数目。

    新方法介绍

        public final void notifyDataSetChanged()
        public final void notifyItemChanged(int position)
        public final void notifyItemRangeChanged(int positionStart, int itemCount)
        public final void notifyItemInserted(int position) 
        public final void notifyItemMoved(int fromPosition, int toPosition)
        public final void notifyItemRangeInserted(int positionStart, int itemCount)
        public final void notifyItemRemoved(int position)
        public final void notifyItemRangeRemoved(int positionStart, int itemCount) 
  • notifyDataSetChanged() 和ListView中的一样
  • notifyItemChanged(int position) position数据发生了改变,那调用这个方法,就会回调对应position的onBindViewHolder()方法了,当然,因为ViewHolder是复用的,所以如果position在当前屏幕以外,也就不会回调了,因为没有意义,下次position滚动会当前屏幕以内的时候同样会调用onBindViewHolder()方法刷新数据了。其他的方法也是同样的道理。
  • notifyItemRangeChanged(int positionStart, int itemCount) 刷新从positionStart开始itemCount数量的item
  • notifyItemInserted(int position) 在第position位置被插入了一条数据的时候可以使用这个方法刷新,注意这个方法调用后会有插入的动画,这个动画可以使用默认的,也可以自己定义。
  • notifyItemMoved(int fromPosition, int toPosition) 这个方法是从fromPosition移动到toPosition为止的时候可以使用这个方法刷新。
  • notifyItemRangeInserted(int positionStart, int itemCount) 批量添加
  • notifyItemRemoved(int position) 第position个被删除的时候刷新,同样会有动画
  • notifyItemRangeRemoved(int positionStart, int itemCount) 批量删除

未完待续


本文由 zhanghuayan 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

如果对您有用,您的支持将鼓励我继续创作!