Android 高级控件

接下来一起来认识更高级的控件和更丰富的监听器,以及学会如何使用适配器搭建起数据源和视图界面的桥梁。高级控件篇第的一部分将围绕适配器讲解它是如何在某些高级控件发挥重要作用。本篇控件清单:

1. ListView 列表

2. Spinner 下拉列表

3. GridView 网格视图

4. ViewPager 视图滑动切换工具

那什么是数据适配器Adapter呢?如开头所说,它的作用是把复杂的数据填充在指定视图界面上。常用两种Adapter:ArrayAdapter(用于绑定单一的数据,数据源是数组或集合),SimpleAdapter(用于绑定格式复杂的数据,数据源是特定的泛型集合)。接下来将以ListView为例,看看这两种适配器的使用方法和效果。

1.ListView列表

ListView是最为常用的控件之一,它以列表的形式展示具体内容,并且能够根据数据的长度自适应显示。下图是一个每项数据只有一行文本的ListView效果图,对于这类单一数据,用ArrayAdapter加载数据再合适不过,接下来一起学习一下。

布局界面只需要一个ListView,设置好宽高和id就够了。另外,还常用属性android:divider设置列表分割线的颜色,如透明色#00000000.

在MainActivity用id找到布局中的ListView之后,就是加载适配器的过程了:

可以看到使用过程无非三个步骤:数据源准备->适配器加载数据源->控件加载适配器,在关键的第二步对ArrayAdapter初始化中,提供的三个参数完成了在哪里显示、每一项数据如何显示(这里直接使用安卓提供好一个布局)、显示哪些数据及有多少项这些任务,再set到ListView上,就实现了一开始看到的界面效果。所以ListView只负责加载和管理视图,其他显示内容都是交给Adapter去做的。

当然ListView的每一项Item都是可以被监听的,监听器是OnItemClickListener,其中返回的参数position表示被点击的某项在整个List中的位置,从0起算,这样就能用ListView的getItemAtPosition()方法获取到被点击项的内容:

当点击第一项“wifi”时效果如下:

接下来再看一个页面效果:

在这个ListView能看到每个Item不再是简单的一行,有文字也有图片,这种格式复杂的数据就要用到SimpleAdapter了,还是在main.xml里准备好ListView控件,再回到MainActivity来学习如何用之前学会的三步骤来加载SimpleAdapter吧!

SimpleAdapter 

第一步准备数据源,可以看到数据源dataList是一个特定的泛型集合,这里String代表文字,Object代表图片,然后调用getData()初始化dataList。

每一个Map对应一项Item,为了方便用for循环让每个Item里图标都一样,文字内容递增就可以,然后添加到dataList,这样就完成一个有20项Item的List。这里注意Map键值对里的键名,后面会需要。

第二步适配器加载数据源,在此之前,新建item.xml,这个不难理解,因为在ArrayAdpter例子里我们直接使用系统提供的布局而已。注意要给出TextView和ImageView的id,马上就会用到。

现在又到了关键一步,SimpleAdapter初始化比较复杂,需要用到五个参数,前三个容易理解,后两个就是之前需要留心的两个要点。这一步实现了控件与数据的一一绑定。最后一步加载适配器就大功告成了!


现在再介绍ListView上常用的监听器OnScrollListener,用于监听滚动变化,当用户拉到列表最底下的时候可帮助视图在滚动中加载数据。现在为列表设置监听器listView.setOnScrollListener(this),并实现onScrollStateChanged ()、onScroll()方法。

这里重写第一个方法,能看到事件会返回一个scrollState,它有三个状态值,下图打印出详细描述。因为需要在视图一直滑动到底端给出新的Item,为dataList增添新的map之后,要用到adpter非常关键的方法notifyDataSetChanged()通知适配器数据发生了变化要重新加载数据,这再次印证之前所说数据的显示是适配器的工作而不是列表。

效果如下,可以看到当用户看完20项继续向下拖时就会有源源不断的新内容更新上来。

代码如下:

private ListViewlistView;

    private SimpleAdaptersimpleAdapter;

    private List>dataList;

    @Override

    protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_main);

        listView = findViewById(R.id.listView);

        dataList =new ArrayList<>();

        dataList = getData();

//        simpleAdapter = new SimpleAdapter(this, dataList, ,new String[]{"image", "text"},new int[]{R.id.iv_image, R.id.tv_textView});

        simpleAdapter=new SimpleAdapter(MainActivity.this,dataList,R.layout.item,new String[]{"image", "text"},new int[]{R.id.iv_image, R.id.tv_textView});

        listView.setAdapter(simpleAdapter);

        listView.setOnScrollListener(new AbsListView.OnScrollListener() {

@Override

            public void onScrollStateChanged(AbsListView view, int scrollState) {

switch (scrollState){

case SCROLL_STATE_FLING:

Log.i("zyl", "手指离开屏幕,但由于惯性视图仍在滑动");

                        Map map =new HashMap<>();

                        map.put("image", R.mipmap.ic_launcher);

                        map.put("text", "increase");

                        dataList.add(map);

                        simpleAdapter.notifyDataSetChanged();

break;

                    case SCROLL_STATE_IDLE:

Log.i("zyl", "手机离开屏幕,视图已经停止滑动");

break;

                    case SCROLL_STATE_TOUCH_SCROLL:

Log.i("zyl", "手指没有离开屏幕,视图仍在滑动");

                }

}

@Override

            public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

}

});

    }

private List>getData(){

for (int i=1; i <20; i++){

Map map =new HashMap<>();

            map.put("image", R.mipmap.ic_launcher);

            map.put("text", "file" + (i +1));

            dataList.add(map);

        }

return dataList;

    }

学完这两个常用适配器使用和适用情况之后,对比可看出ArrayAdapter使用起来明显简单许多,思考一个问题,ArrayAdapter的第二个参数如果不用系统提供的列表项布局而是自定义布局,是否也能做到图文并存的效果呢?答案是肯定的,只不过需要自定义一个适配器继承ArrayAdapter并重写一些方法了。下面就来学习如何定制一个ListView界面吧!

这次做一个更好看的界面,准备好小动物的图片就可以开始大展身手了!


回忆一下实例化一个ArrayAdapter时需要的三个参数,其中列表项布局以及适配器的适配类型都是要重新考虑的。那么先就从这开始准备吧!

每个Item都是由左边一张图片和右边一行文本组成的,下面代码中需要解释的是使用tools:的属性在我们预览能看到效果但不会出现在运行后的布局,方便我们提前看效果又不至于影响后续工作。

接着需要准备一个实体类Animal作为适配器的适配类型,这个类里提供动物图片和名称两个属性、用来初始化属性的构造方法以及对应的get方法即可。

然后到了关键一步,创建一个自定义的适配器且继承ArrayAdapter,重写父类一组含三个参数的构造函数,并将列表项子布局的id保存下来。接着重写getView()方法,先用getItem(position)得到当前Item项的Animal实例,再用LayoutInflater系列方法把子布局传入当前布局得到一个View,接着调用这个View的findViewById()找到ImageView和TextView实例,这样就可以把从当前项对象get的内容设置到这两个控件里去显示图片和文字了。

一切准备就绪之后,后面的步骤基本信手拈来了,相信下面这段代码你一定没问题了。

点击某个Item也会有响应:


这里对getView()多提几句,如果我们只是用上面几行代码来运行ListView的话效率会非常低,因为每次为了要显示每个子项去调用getView()方法后都会将布局重新加载一遍,如果能将显示过的Item View缓存起来,以后出现直接复用就能达到提升ListView运行效率的效果了。优化后代码如下:

以下是源代码:

public View getView(intposition,View convertView,ViewGroup parent){Animal animal=getItem(position);View view;ViewHolder viewHolder;if(convertView==null){view=LayoutInflater.from(getContext()).inflate(resourceId,null);viewHolder=new ViewHolder();viewHolder.imageView=(ImageView)view.findViewById(R.id.animal_image);viewHolder.textView=(TextView)view.findViewById(R.id.animal_name);view.setTag(viewHolder);}else{view=convertView;viewHolder=(ViewHolder)view.getTag();}viewHolder.textView.setText(animal.getAnimalName());viewHolder.imageView.setImageResource(animal.getImageId());returnview;}classViewHolder{ImageView imageView;TextView textView;}}

到此学了这么多,相信你对适配器可以熟练使用了吧!只要三步就搞定。想必在其他控件上应用适配器也很容易了,下面快来再认识两个高级控件。

2.Spinner 下拉列表

与ListView类似的,每个下拉列表项对应一个Item,列表项内容一般是文字,用ArrayAdapter就能做到,触类旁通,相信做一个下图所示的下拉列表已经难不倒你了!

选择系统提供的一个布局作为Spinnner的菜单样式,注意是设置在适配器上,这里给Spinner安装监听器是OnItemSelectListener,用适配器和列表都可以定位到某Item,完成后效果如下:


3.GridView 网格视图

从名字中能看出来GridView的特点,它使得每个Item以网格的形式展现,除此之外使用方式和ListView非常相似。下面准备用SimpleAdapter做一个这样的Demo:

GirdView本身还有些常用的属性:android:verticalSpacing(两列之间的间距),android:horizontalSpacing(两行之间的间距),android:numColumns(每行显示多少列,选值为auto_fit表示自动适应展示几列)。

接下来就是GridView绑定SimpleAdapter的过程了,不再细说,需要强调这里把图标和文字分别放在两个数组中且一一对应以便能通过循环得到数据源dataList。监听器是OnItemClickListener

最后为了界面美观,在注册该活动时候设置theme是Black且NoTitleBar,注意被设置成android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"的活动一定继承的是android.app包下Activity,如果是V7兼容包下的AppCompatActivity会导致程序崩溃无法打开。点击运行来看看是不是达到上面的效果了呢?

其实除了这两个常用Adatper,还有一些Adapter也实用,下面通过ViewPager控件再来认识一个Adapter。

4.ViewPager 视图滑动切换工具

ViewPager是android扩展包v4包中的类,这个类可以让用户左右切换当前的视图(View、Fragment都可以),很多APP都用到这个功能,可见其重要程度,因此想用这点篇幅详解ViewPager是完全不够的,这里就仅仅给大家介绍用来帮助ViewPager管理View数据源的适配器PagerAdapter,感受一下风格各样的适配器。

首先在布局里导入v4包两个控件,其中PagerTabStrip是ViewPager子标签,包含在ViewPager里,这里用它作标题。

由于PagerAdapter是抽象类,使用时需要自定义子类。初始化时让这个适配器获取到两个数据源List:页卡List和标题List,之后重写几个方法更好的完善这个适配器的功能。

接着三步骤,在主活动准备好两个List,这里用View.inflate ()方法将布局转化成View对象,数据加载到自定义适配器上,adapter加载到ViewPager即可,又给ViewPager设置监听器OnPageChangeListener监听页卡是否发生变化。另外,我们还获取到控件PagerTabStrip去给标题做些美化工作。

最后效果如图,手指左右滑动就可以实现页面切换了。

其实所有这些Adapter都是从父类BaseAdapter扩展而来的,也就是说我们也可以根据自己的需要自定义一个Adapter继承BaseAdapter,然后具体实现下面4个方法:

由于adapter中含有要显示的数据集合,数据集合中元素个数即可被展示的View个数,每个数据的获取、每个Item View的样式都由adapter控制,每个position位置上数据都绑定到Item View上,这样数据和视图也就结合在一起了。由于篇幅原因不在这里接着具体展开,后续再深入探究。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,165评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,720评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,849评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,245评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,596评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,747评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,977评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,708评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,448评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,657评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,141评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,493评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,153评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,890评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,799评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,685评论 2 272

推荐阅读更多精彩内容