• Android RecyclerView的使用


    RecyclerView是什么?

    RecyclerView是一种新的视图组件,目标是为任何基于适配器的视图提供相似的渲染方式。它被作为ListView和GridView控件的继承者,在最新的support-V7版本中提供支持。

    在开发RecyclerView时充分考虑了扩展性,因此用它可以创建想到的任何种类的的布局。但在使用上也稍微有些不便。这就是Android——要完成一件事情总不是那么容易。

    整体上看RecyclerView架构,提供了一种插拔式的体验,高度的解耦,异常的灵活,通过设置它提供的不同LayoutManager,ItemDecoration , ItemAnimator实现令人瞠目的效果。

    RecyclerView可以实现以下功能:

    ListView的功能

    GridView的功能

    横向ListView的功能

    横向ScrollView的功能

    瀑布流效果

    便于添加Item增加和移除动画

    基本使用

    引入官方提供的V7包

    main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        tools:context=".MainActivity"
        tools:showIn="@layout/activity_main">
    
        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerview"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" />
    </RelativeLayout>

    在java代码中的声明和普通控件是一样的

     recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
           
     recyclerView.setLayoutManager(new GridLayoutManager(this,2));
    
     recyclerView.setAdapter(adapter);

    setLayoutManager需要一个LayoutManager,这个类有三个实现,分别是:

      1.LinearLayoutManager 线性管理器,支持横向、纵向

      2.GridLayoutManager 网格布局管理器

      3.StaggeredGridLayoutManager 瀑布就式布局管理器

    上边的代码使用的是GridLayoutManager展示一个两列的网格布局效果;

    再来说说adapter,RecyclerView包含了一种新型适配器,它也需要使用ViewHolder,使用时需要重写两个主要方法:一个用来展现视图和它的持有者的onCreateViewHolder(ViewGroup parent, int viewType),一个用来把数据绑定到视图上的onBindViewHolder(ViewHolder holder, int position)。这么做的好处是,onCreateViewHolder只有当我们真正需要创建一个新视图时才被调用,不需要检查它是否已经被回收。

    adapter代码:

    public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.myViewHolder> {
        private Context context;
        private List<String> mDatas;
    
    
        public RecyclerAdapter(Context context, List<String> mDatas) {
            super();
            this.context = context;
            this.mDatas = mDatas;
    
        }
    
        @Override
        public myViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            myViewHolder holder = new myViewHolder(LayoutInflater.from(context).inflate(R.layout.item_home, parent, false));
            return holder;
        }
    
        @Override
        public void onBindViewHolder(final myViewHolder holder, int position) {
    
            holder.tv.setText(mDatas.get(position));
    
        }
    
        @Override
        public int getItemCount() {
            return mDatas.size();
        }
    
        class myViewHolder extends RecyclerView.ViewHolder {
            TextView tv;
    
            public myViewHolder(View itemView) {
                super(itemView);
                tv = (TextView) itemView.findViewById(R.id.pos);
            }
        }
    
      
    }

    item代码:

    <?xml version="1.0" encoding="utf-8"?>
    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/pos"
        android:layout_width="144dip"
        android:layout_height="72dip"
        android:background="@color/colorPrimary"
        android:gravity="center"
        android:layout_margin="4dip"
        android:textColor="#ffffff" />

    之所以设置一个4dp的margin是因为RecyclerView并没有为我们提供一个想listview那样的设置分割线的属性,所以可以在item中设置一个margin,当然你其实可以通过RecyclerView的addItemDecoration方法去自定义一个分割线。

     运行上述代码显示效果:

    使用LinearLayoutManager的显示效果

    recyclerView.setLayoutManager(new LinearLayoutManager(this));

    使用StaggeredGridLayoutManager的显示效果

    recyclerView.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.VERTICAL));

    使用StaggeredGridLayoutManager显示瀑布流效果需要在adapter中随机设置一下item的高度

    adapter代码

    public class RecyclerAdapter extends RecyclerView.Adapter<RecyclerAdapter.myViewHolder> {
        private Context context;
        private List<String> mDatas;
    
        private List<Integer> mHeights;
    
        public RecyclerAdapter(Context context, List<String> mDatas) {
            super();
            ... ...
            mHeights = new ArrayList<Integer>();
            for (int i = 0; i < mDatas.size(); i++) {
                mHeights.add((int) (100 + Math.random() * 300));
            }
    }
    @Override public void onBindViewHolder(final myViewHolder holder, int position) { ViewGroup.LayoutParams lp = holder.tv.getLayoutParams(); lp.height = mHeights.get(position); holder.tv.setLayoutParams(lp); ... ... }

    其他代码同上面的adapter一样,这里只贴出增加部分,运行效果如下:

    上述代码中StaggeredGridLayoutManager构造的第二个参数传一个orientation,如果传入的是StaggeredGridLayoutManager.VERTICAL代表有多少列;那么传入的如果是StaggeredGridLayoutManager.HORIZONTAL就代表有多少行。例如改成

    recyclerView.setLayoutManager(new StaggeredGridLayoutManager(3, StaggeredGridLayoutManager.HORIZONTAL));

    相应的Adapter中改成

     @Override
        public void onBindViewHolder(final myViewHolder holder, int position) {
            ViewGroup.LayoutParams lp = holder.tv.getLayoutParams();
            lp.width = mHeights.get(position);
            holder.tv.setLayoutParams(lp);
    }

    运行效果如下

    这里只贴了静态图,其实是可以水平滑动的。

    再来说说item的动画效果,RecyclerView 支持item的自定义动画效果。github上也已经出现了好多自定义的效果,这里贴出一个连接吧

    https://github.com/wasabeef/recyclerview-animators

    当然系统也为我们提供了一个默认的效果

     recyclerView.setItemAnimator(new DefaultItemAnimator());

    一句代码即可,显示效果如下

    adapter中增加两个方法

        public void addData(int position) {
            mDatas.add(position, "New Item");
            notifyItemInserted(position);
        }
    
        public void removeData(int position) {
            mDatas.remove(position);
            notifyItemRemoved(position);
        }

    Activity中调用一下

        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.menu_main, menu);
            return true;
        }
    
        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            int id = item.getItemId();
            switch (id) {
                case R.id.action_add:
                    adapter.addData(1);
                    break;
                case R.id.action_delete:
                    adapter.removeData(1);
                    break;
            }
    
            return super.onOptionsItemSelected(item);
        }

    这里需要注意的是RecyclerView 更新数据使用的是   notifyItemInserted(position)notifyItemRemoved(position)这里和listview的notifyDataSetChanged不同,虽然RecyclerView也提供notifyDataSetChanged方法,但使用notifyDataSetChanged是没有任何动画效果的。


    由于RecyclerView的扩展行非常强,系统并没有为我们提供setOnItemClickListener方法,这就需要我们自己去定义了,我们可以在adapter中自己去定义item回调接口

      public interface OnItemClickLitener {
            void onItemClick(View view, int position);
    
            void onItemLongClick(View view, int position);
        }
    
        private OnItemClickLitener mOnItemClickLitener;
    
        public void setOnItemClickLitener(OnItemClickLitener mOnItemClickLitener) {
            this.mOnItemClickLitener = mOnItemClickLitener;
        }

    在onBindViewHolder中调用

        @Override
        public void onBindViewHolder(final myViewHolder holder, int position) {
            ... ...if (mOnItemClickLitener != null) {
                holder.itemView.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        int pos = holder.getLayoutPosition();
                        mOnItemClickLitener.onItemClick(holder.itemView, pos);
                    }
                });
    
                holder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
                    @Override
                    public boolean onLongClick(View v) {
                        int position=holder.getLayoutPosition();
                        mOnItemClickLitener.onItemLongClick(holder.itemView,position);
                        return true;
                    }
                });
            }
    
    
        }

    Activity中添加以下代码即可

      adapter.setOnItemClickLitener(new RecyclerAdapter.OnItemClickLitener() {
                @Override
                public void onItemClick(View view, int position) {
                    Toast.makeText(MainActivity.this, position + " click",Toast.LENGTH_SHORT).show();
                }
    
                @Override
                public void onItemLongClick(View view, int position) {
                    Toast.makeText(MainActivity.this, position + " LongClick",Toast.LENGTH_SHORT).show();
                }
            });

    运行效果:

    献给那些还对RecyclerView还不太熟悉的兄弟们,需要源码请留言。

    参考资料

    https://github.com/wasabeef/recyclerview-animators

    http://blog.csdn.net/lmj623565791/article/details/45059587

    http://blog.jobbole.com/74208/

  • 相关阅读:
    文件上传漏洞及解决办法
    block,inline和inline-block概念和区别
    java中toString() 、(String)、String.valueOf的区别
    实用的原生js图片轮播
    JSON如何处理-jsonpath使用举例
    gRPC初识
    用Rust写一个控制台的俄罗斯方块
    nginx 反向代理报400错误与Host关系
    JPA分页查询与条件分页查询
    Java reactor响应式编程
  • 原文地址:https://www.cnblogs.com/shiwei-bai/p/4972039.html
Copyright © 2020-2023  润新知