安卓UI控件-AdapterView及其子类

来源:互联网 发布:c语言break函数头文件 编辑:程序博客网 时间:2024/05/18 01:01

简介

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

AdapterView及其之类的继承关系:
这里写图片描述

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

列表视图(ListView)和ListActivity

这里写图片描述
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及其实现类的继承关系图
这里写图片描述
常用的有: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<String> 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<String>(this,android.R.layout.simple_list_item_1,arrData);        listView.setAdapter(arrAdapter);    }}

运行结果:
这里写图片描述

关于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

<?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="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<Map<String,Object>> listItems = new ArrayList<Map<String,Object>>();        for(int i=0;i<title.length;i++){            //每一行数据都是一个Object,然后存入Map中,String自己指定            Map<String,Object> map = new HashMap<String,Object>();            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);    }}

运行结果:
这里写图片描述

关于SimpleAdapter,使用SimpleAdapter的最大难点在于创建SimpleAdapter对象,它需要5个参数:
第一个参数:上下文,这个不用多说,写this即可。
第二个参数:该参数应该是一个List<? extends Map<String,?>>类型的集合对象,该集合中每个Map<String,?>对象生成一个列表项。
第三个参数:该参数指定一个界面布局的ID,这里使用的自己创建的xml布局文件。
第四个参数:该参数是一个String[]类型的参数,该参数决定提取Map<String,?>对象中哪些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里查看运行结果
这里写图片描述

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

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

Map<String, Object> map = new HashMap<String, Object>();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<String> aa = new ArrayAdapter<String>(this,                android.R.layout.simple_dropdown_item_1line, books);        auto = (AutoCompleteTextView)findViewById(R.id.auto);        // 设置Adapter        auto.setAdapter(aa);    }}

运行截图:
这里写图片描述
还有一种MultiAutoCompleteTextView,它允许输入多个提示项,用法类似。

GridView

这里写图片描述
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的基础上进行了扩展,它把应用中的列表项分为几组,每组又可包含多个列表项。
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

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<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,arr1);        Spinner spinner = (Spinner)findViewById(R.id.spinner);        spinner.setAdapter(adapter);    }}

使用方法与上面的类似
这里写图片描述

AdapterViewFlipper 和 StackView

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

<?xml version="1.0" encoding="utf-8"?><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();        }}

这里写图片描述

StackView示例:

<?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: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<Map<String,Object>> list = new ArrayList<Map<String,Object>>();        for(int i=0;i<imageids.length;i++){            Map<String,Object> map = new HashMap<String,Object>();            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();    }}

这里写图片描述
点击上一个、下一个会有动画的切换效果
同样,小心out of memory

阅读全文
0 0
原创粉丝点击