Android框架之路——RecyclerView的使用

来源:互联网 发布:山治 知乎 编辑:程序博客网 时间:2024/06/08 09:28

参考博客:

  • Android RecyclerView 使用完全解析 体验艺术般的控件
  • 这是一篇Android RecyclerView使用介绍哦

Demo下载

     下载链接

遇到的问题

  • android stuido关于在V7包下找不到recyclerview的解决办法

RecyclerView简介

RecyclerView是Android 5.0提供的新控件,该控件用于在有限的窗口中展示大量数据集。RecyclerView架构,提供了一种插拔式的体验,高度的解耦,异常的灵活,通过设置它提供的不同LayoutManager,ItemDecoration , ItemAnimator实现令人瞠目的效果。

RecyclerView比Listview更先进更灵活,对于很多的视图它就是一个容器,可以有效的重用和滚动。当数据动态变化的时候请使用它。

RecyclerView使用结构

  • RecyclerView.Adapter : 创建View并将数据集合绑定到View上
  • ViewHolder : 持有所有的用于绑定数据或者需要操作的View
  • LayoutManager : 布局管理器,负责摆放视图等相关操作
  • ItemDecoration : 负责绘制Item附近的分割线,通过RecyclerView.addItemDecoration()使用
  • ItemAnimator : 为Item的操作添加动画效果,如,增删条目等,通过RecyclerView.setItemAnimator(new DefaultItemAnimator())使用

前俩条使用过Listview优化的一定不会陌生,后三条则用来自定义布局,分界线和动画效果。

使用流程

>1、基础使用

  1. 创建project,导入v7包;
  2. 修改activity_main.xml,添加RecycleView布局;

    <?xml version="1.0" encoding="utf-8"?><LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/activity_main"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    tools:context="com.ping.recyclerview.MainActivity">    <android.support.v7.widget.RecyclerView        android:id="@+id/recyclerView"        android:layout_width="match_parent"        android:layout_height="match_parent" /></LinearLayout>
  3. 新增item.xml,包含一个TextView;

    <?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"             android:layout_width="match_parent"             android:background="#abcdef"             android:layout_height="wrap_content" >    <TextView        android:id="@+id/id_num"        android:layout_width="match_parent"        android:layout_height="50dp"        android:gravity="center"        android:text="1" /></FrameLayout>
  4. 新建一个MyRecyclerViewAdapter.java,继承自RecyclerView.Adapter,同时泛型中添加上一个ViewHolder,实现三个方法,如下:

    public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.MyViewHolder>{    @Override    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        return null;    }    @Override    public void onBindViewHolder(MyViewHolder holder, int position) {    }    @Override    public int getItemCount() {        return 0;    }    public class MyViewHolder extends RecyclerView.ViewHolder {        public MyViewHolder(View itemView) {            super(itemView);        }    }}
  5. 实现MyRecyclerViewAdapter中的方法;

    public class MyRecyclerViewAdapter extends RecyclerView.Adapter<MyRecyclerViewAdapter.MyViewHolder>{    private List<String> data;    private Context mContext;    public MyRecyclerViewAdapter(List<String> data, Context context) {        super();        this.data = data;        this.mContext = context;    }    @Override    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        View view = LayoutInflater.from(mContext).inflate(R.layout.item, parent, false);        MyViewHolder holder = new MyViewHolder(view);        return holder;    }    @Override    public void onBindViewHolder(MyViewHolder holder, int position) {        holder.mTextView.setText(""+data.get(position));    }    @Override    public int getItemCount() {        return data.size();    }    public class MyViewHolder extends RecyclerView.ViewHolder {        TextView mTextView;        public MyViewHolder(View itemView) {            super(itemView);            mTextView = (TextView) itemView.findViewById(R.id.id_num);        }    }}
  6. 实现MainActivity.java;

    public class MainActivity extends AppCompatActivity {    private RecyclerView mRecyclerView;    private List<String> mDatas;    @Override    protected void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initData();        mRecyclerView = (RecyclerView) findViewById(R.id.recyclerView);        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));        mRecyclerView.setAdapter(new MyRecyclerViewAdapter(mDatas, this));    }    protected void initData()    {        mDatas = new ArrayList<>();        for (int i = 'A'; i < 'z'; i++)        {            mDatas.add("" + (char) i);        }    }}
  7. 实现效果;

>2、进阶使用

  1. 设置点击事件

    • Adapter中添加接口,这种方法的思想是通过setter方法给Adapter注入OnRecyclerViewItemClickListener接口实例,注入实例时要对应实现接口中的监听长短按的方法。注入实例后的Adapter可以使用实例的俩个方法,对Adapter来说此时就美滋滋…直接可以调用了。这里给出的只是一种写法,网上还有其他写法,思想类似,可参照。

      ......private OnRecyclerViewItemClickListener mOnRecyclerViewItemClickListener;public MyRecyclerViewAdapter(List<String> data, Context context) {    super();    this.data = data;    this.mContext = context;}public void setOnRecyclerViewItemClickListener(OnRecyclerViewItemClickListener onRecyclerViewItemClickListener) {    mOnRecyclerViewItemClickListener = onRecyclerViewItemClickListener;}public interface OnRecyclerViewItemClickListener {    void onItemClick(View view, int position);    void onItemLongClick(View view, int position);}.......@Overridepublic void onBindViewHolder(MyViewHolder holder, final int position) {    holder.mTextView.setText(""+data.get(position));    if(mOnRecyclerViewItemClickListener!=null){        holder.itemView.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                mOnRecyclerViewItemClickListener.onItemClick(v, position);            }        });        holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {            @Override            public boolean onLongClick(View v) {                mOnRecyclerViewItemClickListener.onItemLongClick(v, position);                return true;            }        });    }}......
    • MainActivity中实现接口中的方法

      ....mAdapter = new MyRecyclerViewAdapter(mDatas, this);mAdapter.setOnRecyclerViewItemClickListener(new MyRecyclerViewAdapter.OnRecyclerViewItemClickListener() {    @Override    public void onItemClick(View view, int position) {        Log.i("MainActivity", "short");    }    @Override    public void onItemLongClick(View view, int position) {        Log.i("MainActivity", "long");    }});mRecyclerView.setAdapter(mAdapter);.....
  2. 设置分割线

    • 参考博客有对应的实现方案,这里就照搬一下了;

      public class DividerItemDecoration extends RecyclerView.ItemDecoration {    private static final int[] ATTRS = new int[]{            android.R.attr.listDivider    };    public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;    public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;    private Drawable mDivider;    private int mOrientation;    public DividerItemDecoration(Context context, int orientation) {        final TypedArray a = context.obtainStyledAttributes(ATTRS);        mDivider = a.getDrawable(0);        a.recycle();        setOrientation(orientation);    }    public void setOrientation(int orientation) {        if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {            throw new IllegalArgumentException("invalid orientation");        }        mOrientation = orientation;    }    @Override    public void onDraw(Canvas c, RecyclerView parent) {        Log.v("itemdecoration", "onDraw()");        if (mOrientation == VERTICAL_LIST) {            drawVertical(c, parent);        } else {            drawHorizontal(c, parent);        }    }    public void drawVertical(Canvas c, RecyclerView parent) {        final int left = parent.getPaddingLeft();        final int right = parent.getWidth() - parent.getPaddingRight();        final int childCount = parent.getChildCount();        for (int i = 0; i < childCount; i++) {            final View child = parent.getChildAt(i);            android.support.v7.widget.RecyclerView v = new android.support.v7.widget.RecyclerView(parent.getContext());            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child                    .getLayoutParams();            final int top = child.getBottom() + params.bottomMargin;            final int bottom = top + mDivider.getIntrinsicHeight();            mDivider.setBounds(left, top, right, bottom);            mDivider.draw(c);        }    }    public void drawHorizontal(Canvas c, RecyclerView parent) {        final int top = parent.getPaddingTop();        final int bottom = parent.getHeight() - parent.getPaddingBottom();        final int childCount = parent.getChildCount();        for (int i = 0; i < childCount; i++) {            final View child = parent.getChildAt(i);            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child                    .getLayoutParams();            final int left = child.getRight() + params.rightMargin;            final int right = left + mDivider.getIntrinsicHeight();            mDivider.setBounds(left, top, right, bottom);            mDivider.draw(c);        }    }    @Override    public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {        if (mOrientation == VERTICAL_LIST) {            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());        } else {            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);        }    }}
    • 在MainActivity.java中增加一行,为RecyclerView设置分割线;

      mRecyclerView.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL_LIST));
    • 实现效果:

    • 自定义分割线

      1、在styles.xml中重定义系统的listDivider,如下:

          <resources>        <!-- Base application theme. -->        <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">            <!-- Customize your theme here. -->            <item name="colorPrimary">@color/colorPrimary</item>            <item name="colorPrimaryDark">@color/colorPrimaryDark</item>            <item name="colorAccent">@color/colorAccent</item>            <item name="android:listDivider">@drawable/divider_bg</item>        </style>    </resources>

      2、在drawable下创建divider_bg.xml;

          <?xml version="1.0" encoding="utf-8"?>    <shape xmlns:android="http://schemas.android.com/apk/res/android"           android:shape="rectangle" >        <gradient            android:centerColor="#abc"            android:endColor="#fff"            android:startColor="#000"            android:type="linear" />        <size android:height="4dp"/>    </shape>

      3、实现效果,有点丑,但是功能到位就好。(宽度可以通过上面的height设置)

  3. 设置布局

    我们通过mRecyclerView.setLayoutManager(new LinearLayoutManager(this))来设置了布局为线性布局,系统共提供了三个布局,分别是:

    • LinearLayoutManager 线性管理器,支持横向、纵向;
    • GridLayoutManager 网格布局管理器;
    • StaggeredGridLayoutManager 瀑布流式布局管理器

    下面我们来进行另外俩种布局管理器的学习演示。

    • GridLayoutManager

      1、更改设置布局的代码,第二个参数为几列;

      mRecyclerView.setLayoutManager(new GridLayoutManager(this, 3));

      2、给Item设置margin,中间留白;

      <?xml version="1.0" encoding="utf-8"?><FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"             android:layout_width="match_parent"             android:background="#abcdef"             android:layout_marginLeft="1dp"             android:layout_marginRight="1dp"             android:layout_marginTop="1dp"             android:layout_marginBottom="1dp"             android:layout_height="wrap_content" >    <TextView        android:id="@+id/id_num"        android:layout_width="match_parent"        android:layout_height="50dp"        android:gravity="center"        android:text="1" /></FrameLayout>

      3、效果如下;

    • StaggeredGridLayoutManager

      1、使用StaggeredGridLayoutManager同样可以实现上面GridLayoutManager的效果。

      mRecyclerView.setLayoutManager(new StaggeredGridLayoutManager(4, StaggeredGridLayoutManager.VERTICAL));

      2、效果如下;

    • 使用StaggeredGridLayoutManager实现瀑布流的效果,修改Adapter如下:

      ....private List<Integer> mHeights;....public MyRecyclerViewAdapter(List<String> data, Context context) {    super();    this.data = data;    this.mContext = context;    mHeights = new ArrayList<Integer>();    for (int i = 0; i < data.size(); i++)    {        mHeights.add( (int) (150 + Math.random() * 200));    }}....@Overridepublic void onBindViewHolder(MyViewHolder holder, final int position) {    holder.mTextView.setText(""+data.get(position));    ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();    layoutParams.height = mHeights.get(position);    if(mOnRecyclerViewItemClickListener!=null){        holder.itemView.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                mOnRecyclerViewItemClickListener.onItemClick(v, position);            }        });        holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {            @Override            public boolean onLongClick(View v) {                mOnRecyclerViewItemClickListener.onItemLongClick(v, position);                return true;            }        });    }}
    • 效果如下:



个人公众号:每日推荐一篇技术博客,坚持每日进步一丢丢…欢迎关注,想建个微信群,主要讨论安卓和Java语言,一起打基础、用框架、学设计模式,菜鸡变菜鸟,菜鸟再起飞,愿意一起努力的话可以公众号留言,谢谢…

0 0
原创粉丝点击