安卓UI控件-AdapterView及其子类

简介

AdapterView的内容一般是包含多项相同格式资源的列表,本身是一个抽象基类,它派生的子类用法很相似,只是显示界面有些不同。

AdapterView及其之类的继承关系:
安卓UI控件-AdapterView及其子类_第1张图片

特征:
AdapterView继承自ViewGroup,本质是个容器
AdapterView可以包含多个“列表项”,并将这多个列表项以合适的形式展示
AdapterView显示的列表项内容由Adapter提供
它派生的子类在用法上也基本相似,只是在显示上有一定区别,因此把他们也归为一类。
由AdapterView直接派生的三个类:
AbsListView、AbsSpinner、AdapterViewAnimator
平常用的多的是上图中第四行以下的子类,需要注意的是Gallery是一个过时的API,可以使用HorizontalScrollView替代

列表视图(ListView)和ListActivity

安卓UI控件-AdapterView及其子类_第2张图片
ListView是一种使用非常广泛的组件,它以垂直列表的形式显示所有列表项。
有两种方式创建:
1.直接使用ListView控件进行创建,这种方式最常见
2.让Activity继承ListActivity,相当于让该Activity显示的组件为ListView

创建ListView后,接下来就要为ListView设置它将要显示的列表项了,可以通过android:entries属性设置一个资源文件上去,推荐的方法是通过setAdapter(Adapter)方法为之提供一个适配器,适配器提供列表项即可。
AbsListView常用的XML属性及相关方法

XML属性 相关方法 说明
android:choiceMode 设置AbsListView的选择行为:
none:不显示任何选中项
singleChoice:允许单选
multipleChoice:允许多选
multipleChoiceModal:允许多选
android:drawSelectorOnTop setDrawSelectorOnTop(boolean) 如果设置该属性为true,选中的列表项将会显示在上面
android:fastScrollEnabled 设置是否允许快速滚动,如果设置为true,将会显示滚动图标,并允许用户拖动该滚动图标进行快速滚动
android:smoothScrollbar setSmoothScrollbarEnabled(boolean) 如果设置为true,列表会使用更精确的基于条目在屏幕上的可见像素高度的计算方法。 默认该属性为真,如果你的适配器需要绘制可变高的条目,他应该设为假。 当该属性为真时,你在适配器在显示变高条目时,滚动条的把手会在滚动的 过程中改变大小。当设为假时,列表只使用适配器中的条目数和屏幕上的 可见条目来决定滚动条的属性
android:stackFromBottom 用于 ListView 和 GridView,指示他们的内容栈从底部开始
android:transcriptMode 设置该组件的滚动模式:
disable:关闭滚动,这是默认值
normal:当该AbsListView收到数据改变通知,且最后一个列表项可见时,该AbsListView将会滚动到底端
alwayScroll:该AbsListView总会自动滚动到底端

ListView常用的XML属性

XML属性 说明
android:divider 设置List列表项的分隔条,即可用颜色分割也可用drawable分割
android:dividerHeight 设置分隔条的高度
android:entries 指定一个数组资源,用于生成列表项
android:footerDividersEnabled 是否在footer View之前绘制分隔条
android:headerDividersEnabled 与上面的类似,是否在header View之后绘制分隔条

数据适配器

Adapter及其实现类的继承关系图
安卓UI控件-AdapterView及其子类_第3张图片
常用的有:ArrayAdapter、SimpleAdapter、SimpleCursorAdapter、BaseAdapter。
作用:把复杂的数据(数组、链表、数据库、集合等)填充在指定视图界面上。
最常用的两种适配器:
ArrayAdapter(数组适配器),用于绑定单一的数据,数据源可以是集合或数组。
SimpleAdapter(简单适配器),用于绑定格式复杂的数据,数据源只能是特定泛型的集合。
数据适配器是连接数据源和视图界面的桥梁,起中介的作用。
实现过程:新建适配器->添加数据源到适配器->视图加载适配器

ListView的使用

首先在布局文件中添加ListView控件

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

使用一个数组适配器来连接数据源,然后视图绑定适配器

public class Test1Activity extends AppCompatActivity {
    private ListView listView;
    private ArrayAdapter arrAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test1);
        listView = (ListView)findViewById(R.id.listView);
        String []arrData = {"asde","请问","dasv","fads","sdaf"};
        arrAdapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1,arrData);
        listView.setAdapter(arrAdapter);
    }
}

运行结果:
安卓UI控件-AdapterView及其子类_第4张图片

关于ArrayAdapter,创建ArrayAdapter需要三个参数。
context:上下文,代表了访问整个Android应用的接口,几乎创建所有组件都需要传入Context对象。
textViewResourceId:一个资源ID,该资源ID代表一个TextView,作为ListView中每行的样式,上面例子使用的安卓系统自带的样式,也可以使用自定义的样式,需要注意的是XML的根结点只能是TextView。
数组或List:该数组或List将负责为多个列表项提供数据。

下面使用SimpleAdapter实现图文并茂的ListView
SimpleAdapter比ArrayAdapter要复杂一些,但是功能更为强大。
首先还是在布局文件中添加ListView控件
activity_main.xml

    <ListView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/lv1"
        android:drawSelectorOnTop="true">
    ListView>

然后创建一个图文的布局文件,用于ListView的每一个表项的布局
simpleadaitem.xml


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ImageView
        android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingStart="10dp"
        android:adjustViewBounds="true"
        android:maxWidth="100dp"/>
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <TextView
            android:id="@+id/title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
        <TextView
            android:id="@+id/author"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    LinearLayout>
LinearLayout>

关键的部分,创建一个SimpleAdapter,添加数据源,绑定到视图

package com.example.admin.test3;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Test2Activity extends AppCompatActivity{

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test2);
        //获取布局中的ListView
        final ListView lv1 = (ListView)findViewById(R.id.lv1);
        //获取图片资源文件
        int [] images = new int[]{R.drawable.img4,R.drawable.img5,R.drawable.img6,R.drawable.img7};
        String []title = new String[]{"实战大数据——","白话深度学习与","Unity 3D\\2D手机游戏开发:从学习","Web前端自动化构"};
        String []author = new String[]{"许国根,贾瑛","高扬","金玺曾","[澳]斯特凡·鲍姆加"};
        //将上面的数据添加到List集合中
        List> listItems = new ArrayList>();
        for(int i=0;i//每一行数据都是一个Object,然后存入Map中,String自己指定
            Map map = new HashMap();
            map.put("img",images[i]);
            map.put("title",title[i]);
            map.put("author",author[i]);
            listItems.add(map);
        }
        //关键的SimpleAdapter
        SimpleAdapter adapter = new SimpleAdapter(this,listItems,
                R.layout.simpleadaitem,new String[]{"img","title","author"},new int[]{R.id.img,R.id.title, R.id.author});
        lv1.setAdapter(adapter);
    }
}

运行结果:
安卓UI控件-AdapterView及其子类_第5张图片

关于SimpleAdapter,使用SimpleAdapter的最大难点在于创建SimpleAdapter对象,它需要5个参数:
第一个参数:上下文,这个不用多说,写this即可。
第二个参数:该参数应该是一个List>类型的集合对象,该集合中每个Map对象生成一个列表项。
第三个参数:该参数指定一个界面布局的ID,这里使用的自己创建的xml布局文件。
第四个参数:该参数是一个String[]类型的参数,该参数决定提取Map对象中哪些key对应的value来生成列表项,所以填写map.put(key,Value)对应的key即可。
第五个参数:该参数是一个int[]类型的参数,该参数决定填充哪些组件,填写自定义的xml布局文件中控件的ID即可,相当于把第四个参数指定的数据填充到第五个控件指定的控件中,与第四个参数形成对应关系。

ListView的监听事件

OnItemClickListener:
可以处理视图中单个条目的点击事件

        final TextView tv2 = (TextView)findViewById(R.id.tv2);
        lv1.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView adapterView, View view, int i, long l) {
                TextView name = (TextView) view.findViewById(R.id.author);
                tv2.setText(name.getText());
            }
        });

这段代码的作用是将点击到的条目中author内容显示到TextView中

onItemClick的参数:
adapterView是识别是哪个ListView发生的点击事件。
view是点击到的那一item的view的布局,就是可以用这个view,获取里面的控件的id后操作控件。
i是当前item在ListView中适配器里的位置。
l是当前item在ListView里的第几行的位置。

OnScrollListener:
ListView的滚动事件,监听滚动事件,可以做到下拉刷新,下拉显示更多列表的操作。

        lv1.setOnScrollListener(new AbsListView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(AbsListView absListView, int i) {
                switch(i){
                    case SCROLL_STATE_FLING:
                        Log.i("Main", "用户在手指离开屏幕之前,由于用力滑了一下,视图仍在滚动");
                        break;
                    case SCROLL_STATE_IDLE:
                        Log.i("Main", "视图已经停止滚动");
                        break;
                    case SCROLL_STATE_TOUCH_SCROLL:
                        Log.i("Main", "手指没有离开屏幕,视图正在滑动");
                        break;
                }
            }
            @Override
            public void onScroll(AbsListView absListView, int i, int i1, int i2) {

            }
        });

在Logcat里查看运行结果
安卓UI控件-AdapterView及其子类_第6张图片

我们可以在onScrollStateChanged中进行判断,主要判断一下条件;

是否是停止状态
是否滑倒最后
是否正在加载数据
如果符合条件,则开始加载数据,通过接口回调,然后ListView加载更多数据。

Map map = new HashMap();
map.put("image",R.mipmap.ic_launcher);
map.put("text","我是拉到最下边没有之后刷新添加的");
dataList.add(map);
simple_adapter.notifyDataSetChanged();//适配器对象调用

notifyDataSetChange()方法,告诉UI界面更新告诉UI界面更新。
在屏幕下滑时,动态的加载入新的数据,也就是在Map中添加新的数据map.put(…),添加到SimpleAdapter初始化时用到的数据源dataList中dataList.add(map),同时适配器通知UI线程有数据更新。

BaseAdapter

BaseAdapter是一个抽象类,使得用户可以灵活的使用列表项,现在用BaseAdapter重新实现上例。

package com.example.admin.test3;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

public class Test3Activity extends AppCompatActivity {

    private ListView myList;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test3);
        final int [] images = new int[]{R.drawable.img4,R.drawable.img5,R.drawable.img6,R.drawable.img7};
        final String []title = new String[]{"实战大数据——","白话深度学习与","Unity 3D\\2D手机游戏开发:从学习","Web前端自动化构"};
        final String []author = new String[]{"许国根,贾瑛","高扬","金玺曾","[澳]斯特凡·鲍姆加"};

        myList = (ListView)findViewById(R.id.myList);
        BaseAdapter adapter = new BaseAdapter() {
            @Override
            public int getCount() {
                return 4;
            }
            @Override
            public Object getItem(int i) {
                return null;
            }
            @Override
            public long getItemId(int i) {
                return 0;
            }
            @Override
            public View getView(int i, View view, ViewGroup viewGroup) {
                LinearLayout line = new LinearLayout(Test3Activity.this);
                line.setOrientation(LinearLayout.HORIZONTAL);
                ImageView image = new ImageView(getApplicationContext());
                image.setImageResource(images[i]);
                image.setMaxWidth(200);
                image.setAdjustViewBounds(true);
                line.addView(image);

                LinearLayout line2 = new LinearLayout(getApplicationContext());
                line2.setOrientation(LinearLayout.VERTICAL);
                TextView text = new TextView(Test3Activity.this);
                text.setText(title[i]);
                line2.addView(text);
                TextView text2 = new TextView(Test3Activity.this);
                text2.setText(author[i]);
                line2.addView(text2);
                line.addView(line2);
                return line;
            }
        };
        myList.setAdapter(adapter);
    }
}

这部分代码的关键是在于重写了4个方法
getCount():该方法的返回值控制该Adapter将会包含多少个列表项。
getItem(int position):该方法的返回值决定第position处的列表项的内容。
getItemId(int position):该方法的返回值决定第position处的列表项的ID。
getView(int position,View convertView,ViewGroup parent):该方法的返回值决定第position处的列表项组件。

AdapterView的其它子类GridView、Spinner、Gallery和AdapterViewFlipper等用法与ListView相同。

AutoCompleteTextView

自动完成文本框从EditText派生出来,当用户输入一定字符之后,自动完成文本框会显示一个下拉菜单,供用户从中选择,当用户选中某个菜单项之后,自动完成文本框会自动填写该文本框。

实现:
首先在布局文件中添加AutoCompleteTextView

    <AutoCompleteTextView
        android:id="@+id/auto"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:completionHint="请选择您喜欢的图书:"
        android:completionThreshold="1"/>

然后写逻辑代码

package com.example.admin.test3;

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

public class Test1Activity extends AppCompatActivity {

    AutoCompleteTextView auto;
    // 定义字符串数组,作为提示的文本
    String[] books = new String[]{
            "图书1",
            "图书2",
            "图书3",
            "图书4"
    };
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test1);
        // 创建一个ArrayAdapter,封装数组
        ArrayAdapter aa = new ArrayAdapter(this,
                android.R.layout.simple_dropdown_item_1line, books);
        auto = (AutoCompleteTextView)findViewById(R.id.auto);
        // 设置Adapter
        auto.setAdapter(aa);
    }
}

运行截图:
安卓UI控件-AdapterView及其子类_第7张图片
还有一种MultiAutoCompleteTextView,它允许输入多个提示项,用法类似。

GridView

安卓UI控件-AdapterView及其子类_第8张图片
GridView用于在界面上按行、列分布的方式来显示多个组件。
GridView与ListView的区别在于ListView只显示一列,而GridView可以显示多列,它们的用法基本一致。

XML属性 相关方法 说明
android:numColumns setNumColumns(int) 设置列数
android:horizontalSpacing setHorizontalSpacing(int) 设置个元素之间的水平间距
android:verticalSpacing setVerticalSpacing(int) 设置各元素之间的垂直间距
android:columnWidth setColumnWidth(int) 设置列的宽度
android:gravity setGravity(int) 设置对齐方式
android:stretchMode setStretchMode(int) 设置拉伸模式

注意:不能设置行高

ExpandableListView

ExpandableListView是ListView的之类,它在普通ListView的基础上进行了扩展,它把应用中的列表项分为几组,每组又可包含多个列表项。
安卓UI控件-AdapterView及其子类_第9张图片
安卓UI控件-AdapterView及其子类_第10张图片
安卓UI控件-AdapterView及其子类_第11张图片
安卓UI控件-AdapterView及其子类_第12张图片

Spinner

Spinner其实就是一个列表选择框,效果是弹出一个菜单供用户选择。
示例:

    <Spinner
        android:id="@+id/spinner"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
    Spinner>
public class Test1Activity extends AppCompatActivity {

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test1);
        String[] arr1 = new String[]{"驱蚊器","非常","分为","轻轻打发"};
        ArrayAdapter adapter = new ArrayAdapter(this,android.R.layout.simple_list_item_1,arr1);
        Spinner spinner = (Spinner)findViewById(R.id.spinner);
        spinner.setAdapter(adapter);
    }
}

使用方法与上面的类似
安卓UI控件-AdapterView及其子类_第13张图片

AdapterViewFlipper 和 StackView

它们均继承于AdapterViewAnimator,共同特点是支持一定的动画特效,AdapterViewFlipper每次显示一个View组件,程序可通过showPrevious()和showNext()来显示上一个、下一个组件,还可以通过startFlipping()来控制它自动播放下一个View组件。StackView是以堆叠的方式来显示多个列表项。
示例:
使用AdapterViewFlipper实现自动播放的图片库


<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <AdapterViewFlipper
        android:id="@+id/flipper"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:flipInterval="5000"
        android:layout_alignParentTop="true"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentLeft="true"
        android:onClick="prev"
        android:text="上一个"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:onClick="next"
        android:text="下一个"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:onClick="auto"
        android:text="自动播放"/>
RelativeLayout>
package com.example.admin.test3;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterViewFlipper;
import android.widget.BaseAdapter;
import android.widget.ImageView;

public class Test4Activity extends AppCompatActivity {

    int[] imageIds = new int[]{R.drawable.img4,R.drawable.img5,R.drawable.img6,R.drawable.img6,R.drawable.img7 };
    private AdapterViewFlipper flipper;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test4);
        flipper = (AdapterViewFlipper) findViewById(R.id.flipper);
        // 创建一个BaseAdapter对象,该对象负责提供Gallery所显示的列表项
        BaseAdapter adapter = new BaseAdapter()
        {
            @Override
            public int getCount()
            {
                return imageIds.length;
            }
            @Override
            public Object getItem(int position)
            {
                return position;
            }
            @Override
            public long getItemId(int position)
            {
                return position;
            }
            // 该方法返回的View代表了每个列表项
            @Override
            public View getView(int position, View convertView, ViewGroup parent)
            {
                // 创建一个ImageView
                ImageView imageView = new ImageView(getApplicationContext());
                imageView.setImageResource(imageIds[position]);
                // 设置ImageView的缩放类型
                imageView.setScaleType(ImageView.ScaleType.FIT_XY);
                // 为imageView设置布局参数
                imageView.setLayoutParams(new ViewGroup.LayoutParams(
                        ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
                return imageView;
            }
        };
        flipper.setAdapter(adapter);
        }
        public void prev(View source)
        {
            // 显示上一个组件
            flipper.showPrevious();
            // 停止自动播放
            flipper.stopFlipping();
        }
        public void next(View source)
        {
            // 显示下一个组件。
            flipper.showNext();
            // 停止自动播放
            flipper.stopFlipping();
        }
        public void auto(View source)
        {
            // 开始自动播放
            flipper.startFlipping();
        }
}

安卓UI控件-AdapterView及其子类_第14张图片

StackView示例:


<LinearLayout 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"
    android:orientation="vertical"
    tools:context="com.example.admin.test3.Test1Activity">
    <StackView
        android:id="@+id/stackView1"
        android:layout_width="match_parent"
        android:layout_height="400dp"
        android:loopViews="true">
    StackView>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <Button
            android:id="@+id/button2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="上一个"
            android:onClick="prev"/>
        <Button
            android:id="@+id/bututon1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="下一个"
            android:onClick="next"/>
    LinearLayout>
LinearLayout>
public class Test1Activity extends AppCompatActivity {

    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_test1);
        final int imageids[] = new int[]{R.drawable.img5,R.drawable.img6,R.drawable.img7,R.drawable.img4};
        StackView stack = (StackView)findViewById(R.id.stackView1);
        List> list = new ArrayList>();
        for(int i=0;i map = new HashMap();
            map.put("images",imageids[i]);
            list.add(map);
        }
        SimpleAdapter adapter = new SimpleAdapter(this,list,R.layout.cell,
                new String[]{"images"},new int[]{R.id.image1});
        stack.setAdapter(adapter);
    }
    public  void prev(View view){
        StackView stack = (StackView)findViewById(R.id.stackView1);
        stack.showPrevious();
    }
    public void next(View view){
        StackView stack = (StackView)findViewById(R.id.stackView1);
        stack.showNext();
    }
}

安卓UI控件-AdapterView及其子类_第15张图片
点击上一个、下一个会有动画的切换效果
同样,小心out of memory

你可能感兴趣的:(android基础)