ListView(1)控件架构与ArrayAdapter详解

ListView是Android开发中比较常用的一个组件,它以列表的形式展示信息,并能根据信息的长度自适应显示。比如说我们手机里的通讯录就用到了ListView显示联系人信息。在大量的场合下,我们都需要使用这个控件。虽然在Android 5.0时代,RecyclerView在很多地方都在逐渐取代ListView,但ListView的使用范围依然非常的广泛。我们也不能跳过ListView直接去学习RecyclerView,对ListView的透彻理解是十分有必要的。

首先来看ListView在View树中所处的位置:

ListView的官方解释:

A view that shows items in a vertically scrolling list.

The items come from the {@link ListAdapter} associated with this view.

即:一种在垂直滚动列表中显示项目的视图。

显示的项目(数据)通过ListAdapter适配器来与视图关联。

数据适配器是连接数据源和视图界面的桥梁,它用来把复杂的数据(数组、链表、数据库、集合等)填充在指定视图界面上。数据适配器的实现过程为:1.新建适配器–>2.添加数据源到适配器–>3.视图加载适配器

那么ListAdapter是什么适配器呢?Adapter是所有适配器的祖先接口,下图为ListAdapter在所有适配器继承树中的位置:

自定义数据适配器的时候用到了BaseAdapter类,那么ListAdapter和BaseAdapter是什么关系呢?只看名字好像BaseAdapter是ListAdapter的长辈,但实际上ListAdapter是所有可以用于ListView的适配器的祖先,且仅仅为一个接口。下面为ListAdapter的继承树:

这样,显示的项目(数据)通过ListAdapter适配器来与视图关联这句话的含义便很易理解了,不管是ArrayAdapter、SimpleAdapter、SimpleCursorAdapter或者自定义BaseAdapter,只要这些适配器实现了ListAdapter接口,就可以统称为ListAdapter适配器,继而用于ListView的数据适配,下面为展开的继承树:

这下我们就不用去询问别人ListView有哪几种适配器了,我们已经自己推导出上图除红锁标记的私有类外的其他适配器都可以给ListView用。下面来看比较常用的四种适配器:ArrayAdapter、SimpleAdapter、SimpleCursorAdapter以及自定义BaseAdapter。

ArrayAdapter(数组适配器)

用于绑定格式单一的数据,数据源可以是集合或数组。

布局文件:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</RelativeLayout>

MainActivity.java 如下:

package com.example.listview;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Adapter;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.SimpleCursorAdapter;

public class MainActivity extends AppCompatActivity {
    private ListView mListView;
    private ArrayAdapter<String> arrayAdapter;
    private String[] data = new String[]{"熊大", "熊二", "跳跳","熊大", "熊二", "跳跳",
            "熊大", "熊二", "跳跳","熊大", "熊二", "跳跳"};//数据源

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mListView = (ListView) findViewById(R.id.listView);
        //1.新建数据适配器   2.添加数据源到适配器
        arrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, data);
        //3.视图加载适配器
        mListView.setAdapter(arrayAdapter);

    }
}

运行效果如下:

到这里对ArrayAdapter的一个简单示例就完成了,那对ArrayAdapter的学习到这就可以结束了吗?可以跳到SimpleAdapter的学习了吗?本来是这么打算的,毕竟最常用的是自定义BaseAdapter数据适配器,ArrayAdapter了解一下就可以了啦。可是…可是我看到了这个:

记得面试官问我缺点的时候我说我的缺点是不求甚解的反面,导致学习进度很慢…BaseAdapter万能适配器什么鬼的你们在后边等着我吧…我们接着来看ArrayAdapter……

上面示例新建数据适配器的方式是上图中的第三种创建方式,要掌握其他创建方式,先要了解参数含义:

context : 当前上下文

resource : item的布局文件

textViewResourceId : item布局文件中的TextView的ID (可不指定)

objects : 数据源 (可不指定)

如果参数resource设置为只含有一个TextView控件(可为TextView衍生出的控件如CheckedTextView)的布局文件,则可不指定textViewResourceId参数,比如上面示例中的android.R.layout.simple_list_item_1就是一个TextView,Item内容直接显示在resource布局中,也就是TextView中。

如果参数resource没有设置成仅含有一个TextView的布局文件,则必须在这个布局文件中包含一个TextView,且必须设置参数textViewResourceId指定其中的TextView的ID。此时Item就不再只是单调的TextView布局,而可以在resource指定的布局文件中自定义。但数据只能显示在其中的TextView中,示例如下:

Item布局文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:id="@+id/within_textview"
    android:layout_height="match_parent">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
        <CheckBox
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </LinearLayout>
</LinearLayout>

新建适配器代码修改为下:

        arrayAdapter = new ArrayAdapter<String>(this, R.layout.item,R.id.textView,data);

运行效果:

看来一开始对ArrayAdapter的定义还是挺准确的:用于绑定格式单一的数据,数据源可以是集合或数组。格式单一的是数据,布局可以自己定义,但是数据只能在一个TextView上显示。这种也可以记作样式丰富但内容简单的,而第一个示例可以记作样式和内容都简单的。如果我们需要展示的内容是仅一个textview承载不了的,还需要其它组件,怎么办?那么有没有一个方法可以实现样式和内容都是丰富的呢?有,但是原生的ArrayAdapter无法实现这个功能,需要自定义一个ArrayAdapter类并重写getView()方法才能实现。

丰富的内容通过User类来实现:

package com.example.listview;

/**
 * Created by yinghao on 2016/6/10.
 */
public class User {
    private String name;
    private int age;
    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public int getAge() {
        return age;
    }
}

丰富的布局通过自定义item布局文件来实现:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:id="@+id/within_textview"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/tv_age"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    </LinearLayout>

将丰富的内容显示在丰富的控件上通过自定义ArrayAdapter类来实现:

package com.example.listview;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.TextView;

/**
 * Created by yinghao on 2016/6/10.
 */
public class MyArrayAdapter extends ArrayAdapter<User> {
    private int resourceId;
    public MyArrayAdapter(Context context, int resource, User[] objects) {
        super(context, resource, objects);
        this.resourceId = resource;
    }
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        User user = getItem(position);
        LinearLayout userListItem = new LinearLayout(getContext());
        String inflater = Context.LAYOUT_INFLATER_SERVICE;
        LayoutInflater vi = (LayoutInflater)getContext().getSystemService(inflater);
        vi.inflate(resourceId, userListItem, true);
        TextView name = (TextView) userListItem.findViewById(R.id.tv_name);
        TextView age = (TextView) userListItem.findViewById(R.id.tv_age);
        name.setText(user.getName());
        age.setText(String.valueOf(user.getAge()));
        return userListItem;
    }
}

MainActivity.java 文件代码如下:

package com.example.listview;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class MainActivity extends AppCompatActivity {
    private ListView mListView;
    private User[] users = new User[10];//数据源

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //准备数据源
        for (int i = 0;i<10;i++) {
            User user = new User("name"+i,15+i);
            users[i] = user;
        }
        mListView = (ListView) findViewById(R.id.listView);
        //1.新建数据适配器  // 2.添加数据源到适配器
        MyArrayAdapter arrayAdapter = new MyArrayAdapter(this, R.layout.item, users);
        //3.视图加载适配器
        mListView.setAdapter(arrayAdapter);
    }
}

显示结果如下:

总结:以上学习了ListView与listAdapter适配器的概念及其关系,然后演绎了ArrayAdapter的三种实现方式,分别是样式和内容都是简单的样式丰富但内容简单的样式和内容都丰富的三种。其中前两种用原生的ArrayAdapter就可以实现,通过对原生ArrayAdapter几种构造方法的研究得出了数据只能显示在TextView上的结论;第三种方式需要自己重写getView()方法,在一定程度上也可以算作自定义Adapter。另外对于绑定的数据可以为格式单一的泛型的数组或集合,上面涉及到的为String数组和User数组,也可以为List集合。

关于ArrayAdapter先学到这,接下来学习SimpleAdapter、SimpleCursorAdapter以及自定义BaseAdapter…

时间: 2024-10-13 06:44:43

ListView(1)控件架构与ArrayAdapter详解的相关文章

第二章 控件架构与自定义控件详解 + ListView使用技巧 + Scroll分析

1.Android控件架构下图是UI界面架构图,每个Activity都有一个Window对象,通常是由PhoneWindow类来实现的.PhoneWindow将DecorView作为整个应用窗口的根View,DecorView将屏幕分成两部分:TitleView和ContentView.ContentView实际上是一个FrameLayout,里面容纳的就是我们在xml布局文件中定义的布局. 为什么调用requestWindowFeature()方法一定要在setContentView()方法调

Android控件架构与自定义控件详解(二)——自定义View

在自定义View时,我们通常会去重写onDraw()方法来绘制View的显示内容.如果该View还需要使用wrap_content属性,那么还必须重写onMeasure()方法.另外,通过自定义attrs属性,还可以设置新的属性配置值. 在View中通常有一些比较重要的回调方法. onFinishInflate():从XML加载组件后回调. onSizeChanged(;:组件大小改变时. onMeasure():回调该方法来进行测量. onLayout():回调该方法来确定显示的位置. onT

Android 控件架构与自定义控件详解

架构: PhoneWindow 将一个 DecorView 设置为整个应用窗口的根 View,这里面所有 View 的监听事件,都通过 WindowManagerService 来接收.DecorView 分为 TitleView 和 ContentView,ContentView 是一个 ID 为 content 的 FrameLayout 在 onCreate() 方法中调用 setContentView() 方法后,ActivityManagerService 会回调onResume() 

Android控件架构与自定义控件详解

基于 <android 群英传 >的读书笔记 View的测量-onMeasure() 测量的模式可以有以下三种: EXACTLY 即精确值模式,当我们将控件的layout_width属性或layout_height属性指定为具体参数值时,系统使用的就是EXACTLY AT_MOST 即最大值模式,当控件的layout_width属性或layout_hright属性是warp_content时,控件大小一般随着控件的子控件或内容的变化而变化,此时控件尺寸只要不超过父控件允许的尺寸即可 UNSPE

使用appearance proxy定制控件的默认外观(详解)

控件的外观,受到tint color,background image, background color等属性的共同影响,通常要修改某个控件对象的外观,就去调用上面属性的相关setter方法(或者其他可以修改它们的方法)就可以了.但是,如果希望整个app中的控件都保持一致的风格,比如所有button的风格(指的是大小,背景图,形状等)都一样,那么一个一个去重复设置每个button的风格,就显得太麻烦了.如果可以给Button类设定一个默认外观,就方便多了.appearance proxy就可以

OpenLayers 之 控件(control)详解

每一个地图应用都应该有一些工具方便用户控制地图的行为,比如缩放,全屏,坐标控件等等,在 OpenLayers 中怎么添加这些工具呢?下面我给大家介绍一下 OpenLayers 中包含的控件种类,并介绍其使用方法.对控件的定制化,和对 OpenLayers 增加控件和优化控件等超出了本文范围. 一.control 类 OpenLayers 中的控件是由 control 类定义的,这是一个虚基类,不负责实例化特定的控件,它的主要作用是让其他具体的种类的控件类实现继承.OpenLayers 中包含的控

【React Native开发】React Native控件之WebView组件详解以及实例使用(22)

转载请标明出处: http://blog.csdn.net/developer_jiangqq/article/details/50676379 本文出自:[江清清的博客] (一)前言 [好消息]个人网站已经上线运行,后面博客以及技术干货等精彩文章会同步更新,请大家关注收藏:http://www.lcode.org 今天我们一起来看一下WebView组件讲解以及使用实例 刚创建的React Native技术交流群(282693535),欢迎各位大牛,React Native技术爱好者加入交流!同

asp.net,关于Listview+DataPager控件使用

关于Listview+DataPager控件使用1.DAL层,根据开始条数+结束条数查询数据.2.BLL层,startRowIndex和maximumRows进行查询.(startRowIndex + 1, maximumRows + startRowIndex + 1);3.使用ObjectDataSource控件,配置数据源,   startRowIndex和maximumRows必须BLL逻辑层定义的方法参数名一致,   SelectCountMethod中添加查询总记录条数方法名.4.使

Android ListView列表控件的简单使用

ListView 列表是我们经常会使用的控件, 如果想要自定义里面的显示的话是挺麻烦的, 需要新建XML.Class SimpleAdapter这两个文件, 较为麻烦. 如果我们只是想显示两.三行文字在上面, 却又不想那么麻烦呢? 那我们只要新建一个XML就够了.  这里以显示一个ListView项里三个TextView为例.  首先我们要创建一个XML文件, 这个XML文件是用来作为单个ListView项布局用的.  list_row.xml[java]<?xml version="1.