【第22期】观点:IT 行业加班,到底有没有价值?

RecyclerView的使用(Android开发必备,替换掉ListView)

原创 2016年05月31日 22:14:33

RecyclerView的使用(Android开发必备,替换掉ListView)

           当有人看了你写的代码,说你现在还在使用ListView?是不是感觉快跟不上时代了啊!不错,今天就带给大家一个ListView的最新升级控件RecyclerView,Android 5.0推出的新控件,不过它在support-v7包,可以往下兼容,当你学会了RecyclerView之后,发现了它的强大,你就会替换到ListView和GridView了。
        
 RecyclerView简介:

         RecyclerView是support-v7包中的新控件,是ListView的升级版,使用方法和基本原理和ListView类似,区别是,RecycleView强行把ListView中的 getView ()方法拆分,把其中的ViewHolder单独封装起来,只需要实现自定定义的ViewHolder就行了,改组件会帮我们自动回收复用每一个item。

RecyclerView相对于ListView的优点:     

        1、可以使用布局管理器LayoutManager来管理RecyclerView的显示方式:水平、垂直、网络、网格交错布局;

        2、自定义item的分割条,实现自定义(不知道是优点还是缺点,见仁见智吧   ( ̄▽ ̄)");

        3、可以控制item的添加和删除的动画,非常自由,可以自定义动画,配合具体场景,效果非常棒;

        4、可以动态的在指定位置添加和删除某一项,而列表不会回到顶部,动态的update列表数据(非常需要);
    
        5、缺点:就是没有OnItemClickListenter(),需要自己在RecycleView内部自定义列表项的点击事件或则长按事件(按需求自己添加);
       
        6、在Material Design中和CardView(和RecycleView同时出现的新控件)配合使用,显示效果非常突出(现在很多新的主流App都使用了这种结构,后面会有demo展示)。


RecycleView的基本使用步骤:
      
       1、模拟对象和获取对象集合数据(这里只是模拟数据)

package com.world.hello.recycleview;

/**
 * 模拟对象数据
 * Created by chengguo on 2016/5/30.
 */
public class SampleModel {
    private String message;

    public SampleModel(String message) {
        this.message = message;
    }

    public void setMessage(String s) {
        message = s;
    }

    public String getMessage() {
        return message;
    }
}

package com.world.hello.recycleview;

import java.util.ArrayList;

/**
 * 模拟数据集合
 * Created by chengguo on 2016/5/30.
 */
public class DemoApp {
    //获取要显示的数据(初始化数据)
    public static ArrayList<SampleModel> getSampleData(int size) {
        ArrayList<SampleModel> sampleData = new ArrayList<SampleModel>(size);
        for (int i = 0; i < size; i++) {
            sampleData.add(new SampleModel("新的列表项 " + i));
        }
        
        return sampleData;
    }
}
       
     2、绘制列表项之间的分割条

                   使用RecyclerView控件通常需要指定列表项的分割条。定制分割条的原理是编写一个RecyclerView.ItemDecoration的子类,并实现onDrawOver方法,在该方法中需要绘制所有列表项之间的分割条。如下所示:

package com.world.hello.recycleview;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.RecyclerView;
import android.view.View;

/**
 * 定制分割线
 * Created by chengguo on 2016/5/30.
 */
public class SampleDivider extends RecyclerView.ItemDecoration {
    //默认分割条Drawable资源的Id
    private static final int[] ATTRS = {android.R.attr.listDivider};
    //分割条的Drawable对象
    private Drawable mDicider;

    public SampleDivider(Context context) {
        TypedArray ta = context.obtainStyledAttributes(ATTRS);
        //获取分割条的drawable对象
        mDicider = ta.getDrawable(0);
        //回收ta所占用的空间
        ta.recycle();

    }

    /**
     * 在改方法中绘制了所有列表项之间的分割条
     *
     * @param c
     * @param parent
     */
    @Override
    public void onDrawOver(Canvas c, RecyclerView parent) {

        //获取列表项距离左边源的距离
        int left = parent.getPaddingLeft();
        //获取列表项距离右边源的距离
        int right = parent.getWidth() - parent.getPaddingRight();
        //获取列表的总数
        int childCount = parent.getChildCount();
        //开始绘制这些列表项之间的分割线
        for (int i = 0; i < childCount; i++) {
            //获取当前的列表
            View child = parent.getChildAt(i);
            //获取当前列表项的布局参数信息
            RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
            //计算分割条左上角的的纵坐标
            int top = child.getBottom() + params.bottomMargin;
            //计算分割条右下角的纵坐标
            int bottom = top + mDicider.getIntrinsicHeight();
            //设置分割条绘制的位置
            mDicider.setBounds(left,top,right,bottom);
            //开始绘制当前列表项下方的分割条
            mDicider.draw(c);
        }
    }
}
 
       3、实现Adapter类

                 就像ListView的adapter一般会继承BaseAdapter一样,RecyclerView也提供了这样的一个基类RecyclerView.Adapter,改基类支持泛型,泛型用于指定列表项中控件。如下:

package com.world.hello.recycleview;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.Random;

/**
 * recycleView的adapter
 * Created by chengguo on 2016/5/30.
 */
public class SampleRecycleAdapter extends RecyclerView.Adapter<SampleRecycleAdapter.ViewHolder>{

    //保存列表项数据
    private final ArrayList<SampleModel> sampleData = DemoApp.getSampleData(30);

    //创建列表项中显示的控件对象(需要使用Adapter指定泛型)
    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        //获取列表项控件LinearLayer对象
        View rowView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item,parent,false);
        return new ViewHolder(rowView);
    }

    //在该方法中设置列表项中显示的值
    @Override
    public void onBindViewHolder(ViewHolder holder, int position) {

        SampleModel rowData = sampleData.get(position);
        holder.textViewSample.setText(rowData.getMessage());
        holder.itemView.setTag(rowData);
    }

    //设置列表项总和
    @Override
    public int getItemCount() {
        return sampleData.size();
    }

    //删除指定列表项的数据
    public void removeData(int position){
        sampleData.remove(position);
        //通知recycleView某个列表项被删除了
        notifyItemRemoved(position);
    }

    //在指定的位置添加一个新的列表项
    public void addItem(int position){
        //使用随机数字
        sampleData.add(position,new SampleModel("新增列表项"+ new Random().nextInt(100)));
        notifyItemInserted(position);
    }

    /**
     * ViewHolder用于存储列表项中显示的控件,(这里只有一个TextView做示例)
     */
    public static class ViewHolder extends RecyclerView.ViewHolder{

        private TextView textViewSample;

        public ViewHolder(View itemView) {
            super(itemView);
            textViewSample = (TextView) itemView.findViewById(R.id.text_view);
        }
    }
}

         注意:SampleRecyclerAdapter类中所有使用@Override的方法都是覆盖的父类的同名方法。这些方法中和ListView对应的Adapter中的方法有些不同,在新Adapter中没有了getView()方法,而是使用onCreateViewHolder和OnBindViewHolder方法。前者用于获取列表项控件,后者用于指定在控件中显示的数据。 还有就是以前数据发生变化时,只能调用notifyDataSetChanged()方法通知数据是否发生变化,现在可以使用notifyItemRemoved()方法告诉具体哪个位置的数据被移除,使用notifyItemInserted()方法通知某一个新的列表项背添加。还有很多新的Api非常实用,如下面图片,就不一一介绍了;



     4、在Activity中使用RecyclerView

          recycleView是Android Support library中的控件,所以需要在Android studio中的app的gradle中添加下面的依赖
compile 'com.android.support:design:23.4.0'
 
          然后就可以使用RecycleView这个控件了,这里实现了RecycleView的动态添加和删除操作。稍微要比listview复杂点,要设置RecycleView的排列方式 、item间的分割线、item增加和删除的动画;具体使用代码如下:

package com.world.hello.recycleview;

import android.app.Activity;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.widget.Button;

public class MainActivity extends Activity {

    //顶部删除按钮
    private Button mDeleteBar;
    //recyclerView
    private RecyclerView mRecyclerView;
    //添加item按钮,这里也是使用Design库里面的一个新控件,就当做一个按钮使用。只是样式很好看
    private FloatingActionButton mAddBtn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mDeleteBar = (Button) findViewById(R.id.delete_btn);
        mAddBtn = (FloatingActionButton) findViewById(R.id.add_item);

        //获取到recyclerView
        mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        //创建LinearLayoutManager
        final LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        //为RecyclerView指定布局管理器对象
        mRecyclerView.setLayoutManager(layoutManager);
        //创建列表项分割线对象
        final RecyclerView.ItemDecoration itemDecoration = new SampleDivider(this);
        //RecyclerView控件指定分割线对象
        mRecyclerView.addItemDecoration(itemDecoration);
        //创建SampleRecyclerAdapter
        final SampleRecycleAdapter sampleRecycleAdapter = new SampleRecycleAdapter();
        //为RecyclerView控件指定Adapter
        mRecyclerView.setAdapter(sampleRecycleAdapter);
        //设置Item增加、移除动画
        mRecyclerView.setItemAnimator(new DefaultItemAnimator());


        //为右下角按钮添加点击事件
        mAddBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //获取第一个可视的列表项的位置,再加上2个位置,为了演示方便
                int positionToAdd = layoutManager.findFirstCompletelyVisibleItemPosition() + 2;
                //在该位置的后面插入新的列表项
                sampleRecycleAdapter.addItem(positionToAdd);
            }
        });

        //为顶部的删除面板添加点击事件
        mDeleteBar.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //获取第一个可视的列表项的位置,再加上2个位置,为了演示方便
                int positionToRemove = layoutManager.findFirstCompletelyVisibleItemPosition() + 2;
                //删除第一个可视的列表项
                sampleRecycleAdapter.removeData(positionToRemove);
                //删除完成后隐藏删除面板
                hideDeleteBar();
            }
        });

        //为RecyclerView控件设置滚动事件
        mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
            //滚动状态变化事件的方法
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                super.onScrollStateChanged(recyclerView, newState);
            }

            //滚动事件方法(判断上下或者左右滚动)
            @Override
            public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
                //如果是垂直显示的列表, dy>0 表示向上滚动,否则表示向下滚动
                //如果是水平显示的列表,dx > 0 表示向右滚动,否则表示向左滚动
                if (dy > 0) {
                    //向上滚动时,隐藏删除面板,
                    if (mDeleteBar.getVisibility() == View.VISIBLE) {
                        hideDeleteBar();
                    }
                } else {
                    //向下滚动时,显示显示面板
                    if (mDeleteBar.getVisibility() == View.GONE) {
                        showDeleteBar();
                    }
                }
            }
        });
    }

    /**
     * 显示删除栏,使用动画效果
     */
    private void showDeleteBar() {
        mDeleteBar.startAnimation(AnimationUtils.loadAnimation(this, R.anim.translate_show));
        mDeleteBar.setVisibility(View.VISIBLE);
    }

    /**
     * 隐藏删除栏,使用动画效果
     */
    private void hideDeleteBar() {
        mDeleteBar.startAnimation(AnimationUtils.loadAnimation(this, R.anim.translate_hide));
        mDeleteBar.setVisibility(View.GONE);
    }
}

 main_activity.xml文件如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app ="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.world.hello.recycleview.MainActivity">

    <Button
        android:id="@+id/delete_btn"
        android:layout_width="match_parent"
        android:layout_height="40dp"
        android:text="删除一项"
        android:background="#4400ffee"
        android:textSize="14dp"/>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/add_item"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:borderWidth="0dp"
        app:rippleColor="#eeff0000"
        android:src="@android:drawable/ic_input_add"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_marginRight="33dp"
        android:layout_marginEnd="33dp"
        android:layout_marginBottom="38dp" />

</RelativeLayout>

list_item.xml文件如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="40dp"
    android:gravity="center_vertical"
    android:orientation="vertical">

    <TextView
        android:id="@+id/text_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center_vertical"
        android:textColor="@android:color/black"
        android:textSize="16sp" />
</LinearLayout>

效果图如下:




点击打开链接下载demo,免积分

下一篇,将详细讲解。recycleView的排列方法、动画和CardView结合的使用示例!

        
版权声明:本文为博主原创文章,未经博主允许不得转载。 举报

相关文章推荐

如何在Android Studio中添加RecyclerView-v7支持包

一直知道RecyclerView可以代替ListView、GridView使用,听说功能很强大,但还没有去学习过。今天想学习,没想到还没开始便撞墙了。输入Recycler,只有这两个东西,没有提示Re...
  • a10615
  • a10615
  • 2016-04-28 01:39
  • 28461

再说Android RecyclerView局部刷新那个坑

关键:public final void notifyItemChanged(int position, Object payload)RecyclerView局部刷新大家都遇到过,有时候还说会遇见图...

程序员升职加薪指南!还缺一个“证”!

CSDN出品,立即查看!

Android RecyclerView更新某条/一条数据

注意:使用notifyItemRemoved(position)更新数据之前,还必须集合中删除该数据:mDatas.remove(position),否则不更新。 更新数据  这里更新数据集不...

RecyclerView的数据更新问题

转载地址:http://www.jianshu.com/p/6ba0d723b2b1 前言 最近在写一个天气预报的APP,主要模仿的是xcc3641/SeeWeather,感兴趣的童鞋...

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

android5.0之后出了一个新控件recyclerview,用来替代经典的listview和gridview,我们在使用时会发现布局文件中没有recyclerview,recyclerview是在...

RecyclerView使用攻略(刷新篇)

继《RecyclerView使用攻略(助力篇)》之后,一直没有更新上下拉刷新的功能实现,主要还是受限于个人现有的技术实力,总觉得没有经过实际打磨的,就不敢有上场的自信。虽说现在已经引用到自己的项目上了...

SwipeRefreshLayout+RecyclerView实现下拉刷新上拉自动加载

在实际开发中,为了节省开发周期,下拉刷新上拉加载通常都会采取使用一些第三方库,典型的就是用PullToRefresh,XListView等等,还有就是谷歌推荐的SwipeRefreshLayout,可...

Android开发之RecyclerView完全解析(一)

本文来自红黑联盟,主要介绍一下recyclerview的基本用法,请看文章!

Android 开发之RecyclerView 实现ListView (一)

1. 今天所介绍的就是通过 Android studio建立工程,然后通过RecycleView 实现ListView。  当然最终的目的是让大家更加认识到RecycleView. 废话不多说,先看最...

ANDROID L——RecyclerView,CardView导入和使用(Demo)

实例详解如何导入和使用Android L新增的两个控件——RecyclerView和CardView
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)