前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android开发笔记(三十八)列表类视图

Android开发笔记(三十八)列表类视图

作者头像
aqi00
发布2019-01-18 10:41:28
2.3K0
发布2019-01-18 10:41:28
举报
文章被收录于专栏:老欧说安卓老欧说安卓

AdapterView

AdapterView顾名思义是适配器视图,Spinner、ListView和GridView都间接继承自AdapterView,这三个视图都存在多个元素并排展示的情况,所以需要引入适配器模式。 适配器视图的特点有: 1、定义了适配器的设置方法setAdapter,以及获取方法getAdapter。适配器用于传入视图展示需要的相关数据。 2、定义了一个数据观察者AdapterDataSetObserver,用于在列表数据发生变化时,可以通过notifyDataSetChanged方法来更新视图。 3、定义了单个元素的点击、长按、选中事件。其中点击方法为setOnItemClickListener,点击监听器为OnItemClickListener;长按方法为setOnItemLongClickListener,长按监听器为OnItemLongClickListener;选中方法为setOnItemSelectedListener,选中监听器为OnItemSelectedListener。

Adapter

适配器Adapter与适配视图是配合使用的,每个适配类视图都要搭配相应的适配器,才能够正常工作。Adapter派生出两个接口SpinnerAdapter和ListAdapter,然后BaseAdapter又同时实现了SpinnerAdapter和ListAdapter,所以实际开发中用的是BaseAdapter及其派生出的子类。

一般情况下自定义适配器继承自BaseAdapter就够用了,当然Android为了方便懒人,专门扩展了两种简单易用的适配器,如ArrayAdapter用于每行只显示文本的情况,而SimpleAdapter用于每行显示左图标右文本的情况。实际开发中,ArrayAdapter多用于Spinner,但是SimpleAdapter却很少使用。像ListView和GridView一般都是直接使用BaseAdapter,并不使用布局过于简单的SimpleAdapter。

Spinner

Spinner是下拉框,用于从一串列表中选择某项。下面是Spinner常用的属性和方法: xml布局上的属性设置: prompt : 指定弹窗的标题视图,在spinnerMode=dialog时有效。该属性值不可直接填字符串,但可通过"@string/..."方式来指定标题文字。 spinnerMode : 下拉列表的显示样式,有dialog弹窗和dropdown下拉两种。不过考虑到用户体验,实际开发中一般用dialog。spinnerMode只能在xml中设置,不能在代码中设置。 代码中的方法: setPrompt : 设置标题文字。 setPromptId : 设置标题视图的资源ID。 setSelection : 设置当前选中哪项。 setAdapter : 设置适配器。源码中的适配器类型是SpinnerAdapter,但该类用起来很麻烦,所以实际中用的一般是ArrayAdapter<String>,ArrayAdapter可以直接传入一个字符串数组。 setOnItemSelectedListener : 设置下拉列表的选中监听器。 下面是Spinner调用的代码例子:

代码语言:javascript
复制
		ArrayAdapter<String> starAdapter = new ArrayAdapter<String>(this,
				R.layout.spinner_item, starArray);
		starAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
		Spinner sp = (Spinner) findViewById(R.id.sp_hello);
		sp.setPrompt("请选择行星");
		sp.setAdapter(starAdapter);
		sp.setOnItemSelectedListener(new MySelectedListener());


	private String[] starArray = {"水星", "金星", "地球", "火星", "木星", "土星"};
	class MySelectedListener implements OnItemSelectedListener {
		public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
			Toast.makeText(MainActivity.this, "您选择的是"+starArray[arg2], Toast.LENGTH_LONG).show();
		}


		public void onNothingSelected(AdapterView<?> arg0) {
		}
	}

代码中用到的spinner_item元素布局的示例如下:

代码语言:javascript
复制
<TextView xmlns:android="http://schemas.android.com/apk/res/android" 
    android:id="@android:id/text1"
    style="?android:attr/spinnerItemStyle"
    android:singleLine="true"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:ellipsize="marquee"
    android:textAlignment="inherit"
    android:textSize="17sp"
    android:textColor="#0000ff" />

上面这个xml布局用到了TextView的三个新属性,说明如下: singleLine : 指定是否单行显示,取值true表示单行,false表示多行。代码中对应的方法是setSingleLine。 ellipsize : 指定字符超出TextView区域时的显示方式,取值说明如下:start表示在字符串开头显示省略号,end表示在字符串末尾显示省略号,middle表示在字符串中间显示省略号,marquee表示以跑马灯方式显示字符串(即从左向右循环滚动,跑马灯方式需同时指定singleLine为true)。代码中对应的方法是setEllipsize。 textAlignment : 指定文本的对齐方式,常见的取值说明如下:inherit表示继承上级视图的对齐方式,center表示文本居中对齐,textStart表示文本开头对齐,textEnd表示文本末尾对齐,viewStart表示视图开头对齐,viewEnd表示视图末尾对齐。该属性在API17后增加,即Android4.2.2以上版本才支持。代码中对应的方法是setTextAlignment。

ListView

ListView是列表视图,用于分行显示列表信息。下面是ListView常用的属性和方法:

ListView的属性和方法

xml布局上的属性设置: divider : 指定分隔线的图形。如需取消分隔线,可设置该属性值为@null dividerHeight : 指定分隔线的高度。注意如果divider设置为@null时,就不可将dividerHeight设置为大于0dp的数值,因为这样可能导致末尾的元素显示不全。 headerDividersEnabled : 指定是否显示列表开头的分隔线。但实际开发中发现这个设置不起作用,即使该属性设置为true,开头也不会显示分隔线。查看ListView的源码,发现分隔线是画在子视图的下方,所以列表上方的分隔线就画不出来了。有种情况是例外,就是如果stackFromBottom设置为true,表示列表从下往上显示,那么此时会显示列表上方的分隔线,而不会显示列表下方的分隔线了。 footerDividersEnabled : 指定是否显示列表末尾的分隔线。 stackFromBottom : 指定列表项是否从下往上显示。 代码中的方法: setDivider : 设置分隔线的图形。 setDividerHeight : 设置分隔线的高度。 setHeaderDividersEnabled : 设置是否显示列表开头的分隔线。该方法实际上不起作用。 setFooterDividersEnabled : 设置是否显示列表末尾的分隔线。 setStackFromBottom : 设置列表项是否从下往上显示。 setAdapter : 设置适配器。ListView使用的适配器一般继承自BaseAdapter。 setOnItemClickListener : 设置点击事件的监听器。 setOnItemLongClickListener : 设置长按事件的监听器。 总结ListView的属性设置有两个注意点(不知算不算Android的bug,呵呵): 1、divider设置为@null时,就不能再设置dividerHeight为非0值,不然列表末尾元素显示有问题; 2、不管是否指定headerDividersEnabled,列表上方的分隔线都不会显示;

ListView的使用方式

Android提供了两种使用ListView的方式: 1、ListActivity方式。首先xml布局中将ListView的id设置为系统id,即“@android:id/list”,然后页面的代码类继承ListActivity。该方式无需在代码中获取ListView的对象,直接调用setListAdapter方法设置适配器,同时实现ListActivity的点击方法onListItemClick来响应点击事件。 2、普通Activity方式。xml布局中ListView的id可自定义,页面的代码类继承自Activity。该方式要从布局文件中获取ListView的对象,然后调用该对象的setAdapter方法设置适配器,并调用ListView对象的setOnItemClickListener方法来设置点击事件的监听器。 两种使用方式的区别如下: 1、ListActivity方式的视图id被设置为系统id,不方便在代码中修改该列表视图的属性; 2、ListActivity方式只实现点击方法、未实现长按方法,不方便响应列表项的长按事件。 3、实际开发中经常自己写个Activity的基类,具体页面都从该Activity基类派生出来。如果有个页面采用ListActivity方式,就无法继承使用这个Activity基类了。 从上面可以看出,ListActivity方式的限制较多,所以实际开发中我们还是使用普通Activity方式来开发ListView。

ListView的示例代码

下面是适配器的代码例子:

代码语言:javascript
复制
import java.util.ArrayList;

import com.example.exmsimplewidgte.R;

import android.annotation.SuppressLint;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.BaseAdapter;
import android.widget.TextView;
import android.widget.Toast;

@SuppressLint({ "DefaultLocale", "InflateParams" })
public class TitleListAdapter extends BaseAdapter 
	implements OnItemClickListener, OnItemLongClickListener {

	private ArrayList<String> mTitleList;
	private LayoutInflater mInflater;
	private Context mContext;

	public TitleListAdapter(Context context, String[] title_list) {
		this.mInflater = LayoutInflater.from(context);
		mContext = context;
		mTitleList = new ArrayList<String>();
		for (int i=0; i<title_list.length; i++) {
			mTitleList.add(title_list[i]);
		}
	}

	@Override
	public int getCount() {
		return mTitleList.size();
	}

	@Override
	public Object getItem(int arg0) {
		return mTitleList.get(arg0);
	}

	@Override
	public long getItemId(int arg0) {
		return arg0;
	}

	@Override
	public View getView(final int position, View convertView, ViewGroup parent) {
		ViewHolder holder = null;
		if (convertView == null) {
			holder = new ViewHolder();
			convertView = mInflater.inflate(R.layout.list_title, null);
			holder.tv_seq = (TextView) convertView.findViewById(R.id.tv_seq);
			holder.tv_title = (TextView) convertView.findViewById(R.id.tv_title);
			convertView.setTag(holder);
		} else {
			holder = (ViewHolder) convertView.getTag();
		}

		holder.tv_seq.setText(""+(position+1));
		holder.tv_title.setText(mTitleList.get(position));
		return convertView;
	}

	public final class ViewHolder {
		public TextView tv_seq;
		public TextView tv_title;
	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
		String desc = String.format("您点击了第%d项,该项的标题是%s", 
				position+1, mTitleList.get(position));
		Toast.makeText(mContext, desc, Toast.LENGTH_LONG).show();
	}

	@Override
	public boolean onItemLongClick(AdapterView<?> parent, View view,
			int position, long id) {
		String desc = String.format("您长按了第%d项,该项的标题是%s", 
				position+1, mTitleList.get(position));
		Toast.makeText(mContext, desc, Toast.LENGTH_LONG).show();
		return true;
	}

}

下面是ListView的调用代码例子:

代码语言:javascript
复制
		String[] weekArray = {"星期一", "星期二", "星期三", "星期四", "星期五"};
		TitleListAdapter titleAdapter = new TitleListAdapter(this, weekArray);
		ListView lv_hello = (ListView) findViewById(R.id.lv_hello);
		lv_hello.setFooterDividersEnabled(true);
		lv_hello.setAdapter(titleAdapter);
		lv_hello.setOnItemClickListener(titleAdapter);
		lv_hello.setOnItemLongClickListener(titleAdapter);

GridView

GridView是网格视图,用于分行分列显示表格信息。下面是GridView常用的属性和方法: xml布局上的属性设置: horizontalSpacing : 指定子视图在水平方向的间距。 verticalSpacing : 指定子视图在垂直方向的间距。 columnWidth : 指定每列的宽度。 numColumns : 指定列的数目。 stretchMode : 指定拉伸的模式。取值说明如下:none表示不做拉伸;columnWidth表示若有空余空间,则拉伸与列宽大小一致;spacingWidth表示若有空余空间,则列宽不变,把空余分配到每列间的空隙;spacingWidthUniform与spacingWidth的区别在于,Uniform方式在每列左边和右边都补上空隙(即每行开头和末尾都补空隙),而spacingWidth在每行开头和末尾不补空隙,只有列与列之间才补空隙。实际开发中一般把模式设置为columnWidth。 listSelector : 指定点击网格时的显示背景。 代码中的方法: setHorizontalSpacing : 设置子视图在水平方向的间距。 setVerticalSpacing : 设置子视图在垂直方向的间距。 setColumnWidth : 设置每列的宽度。 setNumColumns : 设置列的数目。 setStretchMode : 设置拉伸的模式。 setAdapter : 设置适配器。GridView使用的适配器一般继承自BaseAdapter。 setOnItemClickListener : 设置点击事件的监听器。 setOnItemLongClickListener : 设置长按事件的监听器。 实际开发中有时需要设置网格之间表格线的颜色,可惜GridView并未直接给出相应的属性和方法,那得变通处理一下。具体的说,就是给GridView设置整个网格的背景色(例如黑色),以及网格之间的水平间距和垂直间距;然后给每项网格的根布局设置背景色(例如白色),这样只有网格间距是黑色,从而间接画上了黑色表格线。 GridView偶尔会出现5dp的外边框,原因尚不明,要想去除这个该死的抽风边框,可将listSelector属性设置为@null,估计此问题与点击背景有关。 GridView的适配器模板与ListView是一样的,只要换掉代码里的布局文件名以及相关控件名称就好了,所以不再重复贴出GridView的适配器代码。下面是GridView的调用代码例子:

代码语言:javascript
复制
		String[] yearArray = {"鼠年", "牛年", "虎年", "兔年", "龙年", "蛇年",
				"马年", "羊年", "猴年", "鸡年", "狗年", "猪年"};
		ContentGridAdapter contentAdapter = new ContentGridAdapter(this, yearArray);
		GridView gv_hello = (GridView) findViewById(R.id.gv_hello);
		gv_hello.setNumColumns(5);
		gv_hello.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
		gv_hello.setHorizontalSpacing(1);
		gv_hello.setVerticalSpacing(1);
		gv_hello.setAdapter(contentAdapter);
		gv_hello.setOnItemClickListener(contentAdapter);
		gv_hello.setOnItemLongClickListener(contentAdapter);

点此查看Android开发笔记的完整目录

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

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

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • AdapterView
  • Adapter
  • Spinner
  • ListView
    • ListView的属性和方法
      • ListView的使用方式
        • ListView的示例代码
        • GridView
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档