前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android的ListView和RecyclerView的基本用法

Android的ListView和RecyclerView的基本用法

作者头像
指点
发布2019-01-18 17:22:23
1.1K0
发布2019-01-18 17:22:23
举报
文章被收录于专栏:指点的专栏指点的专栏

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

首先我们先来看一下ListView控件的简单用法,比如说我们现在要显示这样一个界面:

这里写图片描述
这里写图片描述

每一行项目是一个ImageView和TextView控件的组合。

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

代码语言:javascript
复制
<?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:

代码语言:javascript
复制
<?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:

代码语言:javascript
复制
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,并且加入我们自己的逻辑:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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文件中加入以下代码:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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:

代码语言:javascript
复制
<?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:

代码语言:javascript
复制
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中加一句代码:

代码语言:javascript
复制
        linearLayoutManager.setOrientation(LinearLayoutManager.HORIZONTAL); // 设置控件内排布方式为水平

如图:

这里写图片描述
这里写图片描述

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

代码语言:javascript
复制
<?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的布局管理类型为网状布局就行了:

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

如图:

这里写图片描述
这里写图片描述

来看看效果:

这里写图片描述
这里写图片描述

ok,和我们预想的一样

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

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017年02月22日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档