Android的ListView和RecyclerView的基本用法

来源:互联网 发布:淘宝武士刀老鼠尾 编辑:程序博客网 时间:2024/05/19 01:13

在Android 5.0 版本之前,为了方便的显示多行数据,形如QQ聊天信息主界面,最常用的选择无非是ListView控件,但是ListView控件本身就有很大的局限性和效率问题(相对于RecyclerView控件)来说,比如说ListView只能竖向滚动显示数据,不能横向滚动显示数据,在一些特殊的需求中,ListView就无能为力了。在Android5.0版本之后,Android官方推出了一个新的控件:RecyclerView ,完全解耦的设计使得RecyclerView比起ListView灵活了太多,应用的场合也非常广泛。那么,就来看一下ListView和RecyclerView的用法和不同之处在哪:

首先我们先来看一下ListView控件的简单用法,比如说我们现在要显示这样一个界面:
这里写图片描述
每一行项目是一个ImageView和TextView控件的组合。

新建一个 Android 工程:
activity_main.xml:

<?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"    android:gravity="center_horizontal"    tools:context="com.example.administrator.listviewandrecycleview.MainActivity">    <ListView        android:id="@+id/listView"        android:layout_width="match_parent"        android:layout_height="match_parent">    </ListView></LinearLayout>

在主布局文件中,我们添加了一个ListView控件,用于接下来的数据显示,之后我们要新建一个布局文件用于显示ListView中的项目数据 color_item.xml:

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="horizontal"    android:layout_width="match_parent"    android:layout_height="wrap_content">    <ImageView        android:id="@+id/colorImageView"        android:layout_width="wrap_content"        android:layout_height="wrap_content" />    <TextView        android:id="@+id/colorNameTextView"        android:layout_marginLeft="10dp"        android:textSize="40sp"        android:layout_width="wrap_content"        android:layout_height="wrap_content" /></LinearLayout>

布局采用线性横向布局,文件中有两个控件ImageView、TextView。分别用于显示颜色和文字,有了控件,那么对应储存信息的类就有眉目了,新建一个类Color.java:

public class Color {    private String colorName;    private int imageId;    public Color(String colorName, int imageId) {        this.colorName = colorName;        this.imageId = imageId;    }    public String getColorName () {        return colorName;    }    public int getImageId() {        return imageId;    }}

一个简单的类,储存的信息对应于我们前面布局文件中显示的信息。

ListView是需要适配器才能显示我们定义的布局文件的,那么我们接下来要为ListView设定一个适配器。这里采用ArrayAdapter作为基类适配器,我们新建一个类ColorAdapter来继承ArrayAdapter,并且加入我们自己的逻辑:

import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ArrayAdapter;import android.widget.ImageView;import android.widget.TextView;import com.example.administrator.listviewandrecycleview.R;import java.util.List;import javax.crypto.spec.PSource;/** * Created by Administrator on 2017/2/21. * 自定义适配器类继承于 ArrayAdapter 类来实现 ListView 控件的数据显示, * ListView 控件只有设置了适配器才能显示数据 */public class ColorAdapter extends ArrayAdapter {    private int itemLayoutId;    public ColorAdapter(Context context, int itemLayoutId, List<Color> objects) {        super(context, itemLayoutId, objects);        this.itemLayoutId = itemLayoutId;    }    /*     * getView方法用于返回ListView中的item 的视图     */    @Override    public View getView(int position, View convertView, ViewGroup parent) {        Color color = (Color) getItem(position);        View view;        /*         * convertView 参数用于储存之前加载好的布局缓存,如果不为空,那么我们可以直接用这个用来给view赋值         * 提高ListView的运行效率         */        if(convertView != null) {            view = convertView;        }else {            /*             * 加载自定义的布局文件,这个方法用于加载布局文件,并且返回一个 View 对象。             * 这样我们就能够在代码中使用布局文件中的各个属性。             * 这里的 inflate 方法的三个参数分别代表:             * 要加载的布局文件Id、为加载的布局文件外层再加一层父布局、第三个参数如果为 true 的话就是把加载的 View 加入父布局中作为子控件。否则就是只在父布局中声明,不添加进入父布局             * 这里我们当然不能加入父布局,因为我们的 View 是要加入 ListView 中作为子控件的             */            view = LayoutInflater.from(getContext()).inflate(itemLayoutId, parent, false);        }        // 获取布局文件中的控件id并且显示对应信息:        ImageView imageView = (ImageView) view.findViewById(R.id.colorImageView);        TextView textView = (TextView) view.findViewById(R.id.colorNameTextView);        imageView.setImageResource(color.getImageId());        textView.setText(color.getColorName());        return view;    }}

在ColorAdapter.java中,我们重写了ArrayAdapter类中的getView方法返回的View作为ListView中的item视图。ok,最后是MainActivity.java:

import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.support.v7.widget.ListViewCompat;import android.view.View;import android.widget.AdapterView;import android.widget.ListView;import android.widget.Toast;import java.util.ArrayList;import java.util.List;import listview.Color;import listview.ColorAdapter;public class MainActivity extends AppCompatActivity {    private String colorName[] = new String[]{            "blue", "colors", "green", "pink", "puple", "yellow"};    private int colorId[];    private static final int colorSum = 6;    List<Color> list = new ArrayList<Color>();    private ColorAdapter colorAdapter = null;    private ListView listView = null;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        initAdapter();        listView = (ListView) findViewById(R.id.listView);        listView.setAdapter(colorAdapter); // 为listView设置适配器        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { // 设置ListView的点击响应事件            /*             * listView的点击事件:第一个参数是item所在的适配器引用,             * 第二个参数是点击的item的View对象,在这里这个View包含了一个ImageView和一个TextView             * (布局文件color_item布局文件中的控件)             * 第三个和第四个参数一般是一样的,代表你点击的item在ListView中的位置             */            @Override            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {                Color color = (Color) list.get(position); // 获取点击的View 中包含的Color 对象                Toast.makeText(MainActivity.this, "颜色名称:" + color.getColorName(), Toast.LENGTH_SHORT).show();            }        });    }    protected void initAdapter() {        colorAdapter = new ColorAdapter(this, R.layout.color_item, list);        colorId = new int[]{R.mipmap.blue, R.mipmap.colors, R.mipmap.green, R.mipmap.pink,                                R.mipmap.puple, R.mipmap.yellow};        for(int i = 0; i < colorSum; i++) {            Color color = new Color(colorName[i], colorId[i]);            list.add(color);        }    }}

在MainActivity.java中我们用一个initAdapter方法来初始化ListView需要显示的数据信息,之后将数据信息加入ColorAdapter对象中并且设置ListView控件的适配器为ColorAdapter对象。基本的步骤就完成了,让我们来看一下效果:
这里写图片描述

ListView简单的用法就是这样了。我们在实际使用的时候可以根据我们自己的需求来设置ListView控件的item布局文件和ListView的点击事件处理。

那么接下来我们来看一下RecyclerView控件的简单用法:我们先用RecyclerView控件来实现上面的功能,你可以选择新建一个Android工程,也可以在上面的ListView控件中的工程中加一个Activity来显示RecyclerView,笔者这里选择的是新建一个Activity来显示RecyclerView:
因为RecyclerView是在android5.0版本新增在support.v7库中,并不是在SDK中,所以我们要进行依赖声明:在app中的build.gradle文件中加入以下代码:

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

并且点击屏幕右上方的sync now,如下图:
这里写图片描述
这里我用的是android studio IDE 个人感觉android studio 相比eclipse在android开放方面好,不过android studio 对电脑性能要求更加高。
好了我们还要知道,RecyclerView控件的适配器必须继承于RecyclerView.Adapter<RecyclerView.ViewHolder> 类并且重写其中的抽象方法,那么我们新建一个适配器类用来适配要在RecyclerView控件中显示的数据:ColorAdapterForRecyclerView.java:

import android.content.Context;import android.support.v7.widget.RecyclerView;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.ImageView;import android.widget.TextView;import android.widget.Toast;import com.example.administrator.listviewandrecycleview.MainActivity;import com.example.administrator.listviewandrecycleview.R;import java.util.List;/** * Created by Administrator on 2017/2/21. */public class ColorAdapterForRecyclerView extends RecyclerView.Adapter<ColorAdapterForRecyclerView.MyViewHolder> {    private List<Color> colorList = null;    private Context myContext = null; // Context对象作为Toast提示的第一个参数    /*     * 新建一个静态内部类MyViewHolder继承于RecyclerView.ViewHolder,根据java多态的特性,     * 我们在上面的泛型参数就可以传入这个类作为参数     */    static class MyViewHolder extends RecyclerView.ViewHolder {        ImageView imageView;        TextView textView;        public MyViewHolder(View view) {            super(view);            imageView = (ImageView) view.findViewById(R.id.colorImageView);            textView = (TextView) view.findViewById(R.id.colorNameTextView);        }    }    public ColorAdapterForRecyclerView(Context context, List<Color> colorList)  {        myContext = context;        this.colorList = colorList;    }    /*     * 重写父类的onCreateViewHolder方法,用于创建MyHolder对象作为RecyclerView的显示子项     * 每个 RecyclerView 控件的 item 调用这个方法之后调用     *  onBindViewHolder 方法之后才能作为一个子项显示在 RecyclerView 控件中     */    @Override    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.color_item, parent, false);        /*         * 为每一个RecyclerView中显示的子项设置点击处理事件         */        view.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                TextView textView = (TextView) v.findViewById(R.id.colorNameTextView);                Toast.makeText(myContext, "颜色名称:" + textView.getText().toString(), Toast.LENGTH_SHORT).show();                }        });        MyViewHolder myViewHolder = new MyViewHolder(view);        return myViewHolder;    }    /*     * 重写父类的onBinderViewHolder方法,用于对RecyclerView中显示在屏幕中的子项设置对应的数据信息     */    @Override    public void onBindViewHolder(MyViewHolder myViewHolder, int position) {        Color color = colorList.get(position);        myViewHolder.imageView.setImageResource(color.getImageId());        myViewHolder.textView.setText(color.getColorName());    }    /*     * 重写父类的getItemCount方法用于返回RecyclerView中一共有多少子项     */    @Override    public int getItemCount() {        return colorList.size();    }}

好了,RecyclerView的适配器已经写好了,接下来我们新建一个布局文件recycler_view_activity.xml:

<?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_recycle_view"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:gravity="center_horizontal"    android:orientation="vertical"    tools:context="com.example.administrator.listviewandrecycleview.RecycleViewActivity">    <android.support.v7.widget.RecyclerView        android:id="@+id/recyclerView"        android:layout_width="match_parent"        android:layout_height="match_parent">    </android.support.v7.widget.RecyclerView></LinearLayout>

这个布局文件就是加入了一个RecyclerView控件,注意我们在使用不是SDK中原本就存在的控件时,要写入这个控件的完整路径名(包括我们自定义的控件),接下来新建一个Activity用于显示RecyclerView,RecyclerViewActivity.java:

import android.os.Bundle;import android.support.v7.app.AppCompatActivity;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import java.util.ArrayList;import java.util.List;import listview.Color;import listview.ColorAdapterForRecyclerView;public class RecyclerViewActivity extends AppCompatActivity {    private RecyclerView recyclerView = null;    private String colorName[];    private int colorId[];    private static final int colorSum = 6;    List<Color> colorList = new ArrayList<Color>();    private ColorAdapterForRecyclerView colorAdapter = null;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_recycle_view);        initAdapter(); // 初始化信息,和ListView中的类似,只是适配器的类型不同        recyclerView = (RecyclerView) findViewById(R.id.recyclerView);        /*         * 因为RecyclerView只负责自己本身的创建和回收,所以RecyclerView中的子项创建、子项布局方式、         * 分割线、动画效果等等都需要我们自己完成,正是这种完全解耦的机制成就了RecyclerView控件的         * 灵活性,里面的东西完全由我们自己的需求来编辑逻辑完成         */        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);        recyclerView.setLayoutManager(linearLayoutManager); // 设置布局方式为线性布局,默认为竖向布局        recyclerView.setAdapter(colorAdapter);    }    protected void initAdapter() {        colorAdapter = new ColorAdapterForRecyclerView(this, colorList);        colorName = new String[]{                "blue", "colors", "green", "pink", "puple", "yellow"};        colorId = new int[]{R.mipmap.blue, R.mipmap.colors, R.mipmap.green, R.mipmap.pink,                R.mipmap.puple, R.mipmap.yellow};        for (int i = 0; i < colorSum; i++) {            Color color = new Color(colorName[i], colorId[i]);            colorList.add(color);        }    }}

好了,大体上的代码我们都完成了,最后在主界面加一个按钮用于启动RecyclerViewActivity就行了。下面看运行结果:
这里写图片描述
这里依然是MainActivity中的显示,多了一个按钮用于启动RecyclerViewActivity。我们点击这个按钮:
这里写图片描述
启动了RecyclerViewActivity之后点击“green”那一行(单击别的行也是可以的),成功显示了我们设定的事件信息。那么接下来如何显示横向的滚动View呢,其实很简单:只需要在RecyclerViewActivity中加一句代码:

        linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); // 设置控件内排布方式为水平

如图:
这里写图片描述

我们还需要对color_item.xml文件进行修改

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:layout_marginLeft="20dp"    android:layout_width="wrap_content"    android:layout_height="wrap_content">    <ImageView        android:id="@+id/colorImageView"        android:layout_width="wrap_content"        android:layout_height="wrap_content" />    <TextView        android:id="@+id/colorNameTextView"        android:layout_marginLeft="10dp"        android:textSize="40sp"        android:layout_width="wrap_content"        android:layout_height="wrap_content" /></LinearLayout>

其实就是把排布方式改为该为竖直方向,使得排版更加美观。好了,再试试:
这里写图片描述
成功了,我们可以左右滑动来显示不同的子项。那么如果要显示网状布局呢?其实也很简单,我们只需要改RecyclerView的布局管理类型为网状布局就行了:

/** 设置网状布局管理器,每一行3个子项,排布方式为竖直方向排布 */StaggeredGridLayoutManager staggeredGriadLayoutManager = new StaggeredGridLayoutManager(                                            3, StaggeredGridLayoutManager.VERTICAL);recyclerView.setLayoutManager(staggeredGriadLayoutManager);

如图:
这里写图片描述
来看看效果:
这里写图片描述
ok,和我们预想的一样

最后,这里只是RecyclerView控件的基本用法,RecyclerView控件的用法很多,我们可以自由的在控件里面加入分割线,子项减少和增加的动画效果等等,我们可以自由的定制属于我们的效果。有兴趣的小伙伴可以看一下这篇博文:为RecyclerView 控件添加分隔线:http://blog.csdn.net/hacker_zhidian/article/details/57487844。

如果博客中有什么不正确的地方,还请多多指点。
谢谢观看。。。

0 0
原创粉丝点击