Android ListView基本使用
来源:互联网 发布:内存数据库有哪些 编辑:程序博客网 时间:2024/06/04 19:26
扯淡
不太喜欢UI设计,一是自身比较偏重功能设计,一是没有艺术美感,不擅长布局。当然,不同的人,有不同的layout。扯远了~
ListView是很常用的,比较基本的控件。但相对于其他普通控件,如TextView,Button之类还是相对繁琐。因此,对其基本使用进行简单的总结。
ListView的分类
这里将ListView分为三类:显示型,控件响应型,数据库绑定型。
显示型,仅显示内容,并无控件响应设计。比如,每行仅包含TextView或者ImageView。通常使用ArrayAdapter(每行仅显示一个String),或SimpleAdapter(可以为多种控件的组合)。
控件响应型,例如每行都有按钮,点击后对该行进行相应操作。通常对BaseAdapter进行继承扩充。这里需要指出的是,若使用SimpleAdapter也可以完成界面的显示,但无法响应控件的监听事件。
数据库绑定型,则是将数据库内容通过cursor与ListView进行绑定,并实现相关数据库操作。通常使用SimpleCursorAdapter。
本篇由于篇幅原因,不对SimpleCursorAdapter进行讲解,在对数据库总结时再做描述。
ArrayAdapter
创建一个ListView需要有两步操作,
(1)给每行Item创建一个布局文件。
(2)给ListView创建一个Adapter。而Adapter的作用就是绑定布局文件和显示数据,将各个数据与对应的控件ID(显示位置)相关联。
先以最简单的显示型为例。
(1)创建布局文件
需要指出的是,由于之后使用的ArrayAdapter,布局文件必须以TextView作为BOOT。
<?xml version="1.0" encoding="utf-8"?><TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/tv_show" android:layout_width="match_parent" android:layout_height="match_parent"></TextView>
(2)创建ArrayAdapter
首先声明控件和私有变量
@BindView(R.id.lv_3)ListView mlv3;private ArrayAdapter<String> mArrayAdapter;
初始化数据源
private List<String> getArrayAdapterViewListData(){ List<String> list=new ArrayList<String>(); list.add("ArrayItem1"); list.add("ArrayItem2"); list.add("ArrayItem3"); list.add("ArrayItem4"); return list; }
创建Adapter
mArrayAdapter=new ArrayAdapter<String>(this,R.layout.arraylistviewitem,getArrayAdapterViewListData());mlv1.setAdapter(mArrayAdapter);
可以看到ArrayAdapter有三个参数:Context(谁来创建),R.layout.arraylistviewitem(每行的布局),getArrayAdapterViewListData()(数据源)。
如果要对数据进行添加,删除或者修改,则仅需要对ArrayAdapter中的数据进行操作,并在此调用mlv1.setAdapter(mArrayAdapter);即可。
ArrayAdapter Demo
例如,通过点击,选择要删除的行,点击ListView下方的删除按钮,删除该行。点击ListView下方的添加按钮,弹出输入窗口,完成新一行的添加
(1)为ListView添加监听事件,以记录被点击的Item的Index.
private int mArrayAdapterCurrentID=-1;
mlv1.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) { mArrayAdapterCurrentID=i; } });
这里需要强调的是onItemClick的后两个参数。
int i,表示position,是指item在ArrayAdapter中的Index。
long l,表示item在list中的行号。从0开始。
两者通常相等,但如果list存在标题栏,则会造成偏移。
(2)更新ArrayAdapter,在删除按钮中添加监听代码
if(mArrayAdapterCurrentID>=0){ mArrayAdapter.remove(mArrayAdapter.getItem(mArrayAdapterCurrentID)); mlv1.setAdapter(mArrayAdapter); mArrayAdapterCurrentID=-1;//删除后,position会发生变化,因此设置positon无效。 }
(3)点击添加按钮,弹出窗口。
弹出窗口并非本文重点,可参考
http://www.cnblogs.com/gzdaijie/p/5222191.html,窗口类型8来实现。
(4)更新ArrayAdapter。
final EditText input=new EditText(this); AlertDialog.Builder addItemDialog=new AlertDialog.Builder(this); addItemDialog.setTitle("add Item"); addItemDialog.setView(input); addItemDialog.setPositiveButton("add", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { if(input.getText()!=null){ String newItem; newItem=input.getText().toString(); if(newItem.length()>0&& mArrayAdapter.getPosition(newItem)<0){ mArrayAdapter.add(newItem); mlv1.setAdapter(mArrayAdapter); mArrayAdapterCurrentID=-1; } } } }); addItemDialog.setNegativeButton("cancel", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int i) { } }); addItemDialog.show();
修改操作,就不再啰嗦,毕竟是删除和添加的组合。
SimpleAdapter
有时,我们的ListView并没有那么简单,可能存在多个显示用的控件,如何将数据与显示位置一一对应?SimpleAdapter便派上用场了。
其实SimpleAdapter与ArrayAdapter最大的不同,仅限于构造函数!
SimpleAdapter(Context context, List<? extends Map<String, ?>> data, int resource, String[] from, int[] to)
context:谁创建我。
data:数据源。所有数据存在于List中,这与arrayAdapter相同。而不同之处在于,每行数据以Map的形式进行保存,而非arrayAdapter中的简单String。每行中的数据单元以key&value的形式存储。
resource:每行所用的layout。
from:Map中的key。
to:与Map中的key所对应的layout中的控件resource ID。这样每行中的数据单元,就与每行中显示位置相对应了。
SimpleAdapter Demo
(1)为每行创建公用的布局文件
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <ImageView android:id="@+id/iv_pic" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" app:srcCompat="@mipmap/ic_launcher_round" /> <TextView android:id="@+id/tv_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="TextView" /> <TextView android:id="@+id/tv_age" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="TextView" /> <TextView android:id="@+id/tv_tel" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="TextView" /></LinearLayout>
(2)组织数据源
private List<Map<String,Object>> getSimpleAdapterViewListData(){ List<Map<String, Object>> list=new ArrayList<Map<String, Object>>(); Map<String, Object> item1=new HashMap<String, Object>(); item1.put("name","user1"); item1.put("age","age1"); item1.put("tel","tel1"); item1.put("pic",R.mipmap.ic_launcher); list.add(item1); .... Map<String, Object> itemN=new HashMap<String, Object>(); itemN.put("name","userN"); itemN.put("age","ageN"); itemN.put("tel","telN"); itemN.put("pic",R.mipmap.ic_launcher); list.add(itemN); return list; }
这里需要注意的是,对于Resource,给出的不是Object(比如, Image对象,Video对象)而是Resource ID,否则Resource将无法显示
(3)构造SimpleAdatpter对象
SimpleAdapterm SimpleAdapter=new SimpleAdapter(this, getSimpleAdapterViewListData(), R.layout.simplelistviewitem, new String[]{"name","age","tel","pic"}, new int[]{R.id.tv_name,R.id.tv_age,R.id.tv_tel,R.id.iv_pic});
Key与Resource ID一一对应。
(4)显示
mlv1.setAdapter(mSimpleAdapter);
对于添加/修改/删除操作,就不再多说了,实现上跟arrayAdapter并无不同。
BaseAdapter
开篇也提过,若ListView中存在需要监听的控件(例如,每行中都存在按钮,点击后,对该行进行相应操作),那么SimpleAdapter便无能为力了,我们需要从BaseAdapter进行重新继承。当然,SimpleAdapter和ArrayAdapter都是BaseAdapter的子类。
BaseAdapter是一抽象类,继承BaseAdapter后,需要实现以下四个接口。
@Override public int getCount() { return 0; } @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) { return null; }
(1)getView()
其中最为重要的是getView方法。该方法用于显示ListView中每行的内容。
先解释一下getView中的重要参数。
i:position,即当前行所显示的内容在Adapter数据源中的位置。
view:容器view,即每行的布局。可以从该对象中调用findViewbyID,来获取对应的控件对象。
系统为了加快显示速度,同时又控制资源的使用,会把最近使用的View暂放于内存。例如,ListView有N条记录,且整个ListView无法全部显示。当拖到滚动条时,ListView会调用getView显示各行。
当系统资源不足时,会释放部分内存。因此,在实现该getView方法时,需要对容器view进行是否为null的判断。
如果为空,则需要重新初始化View(该行)中的各个控件变量,并用View的setTag,保存控件变量组,我们称为holder,可以视为Views,即该行的控件组合。
如果不为空,则调用View的getTag获取该行的控件组合。
(2)Holder
Holder可以看做是一个组合,该组合包含了该行中所包括的所有控件。
那么问题来了。
如何对Holder中的控件进行初始化呢?view.findViewbyId(R.id.xxxx)。view即为getView的第二个传参。有了控件,我们便可以对其设置监听了。
如果资源不足,导致view为null,我们该如何获取view呢?
view=LayoutInflater.from(context).inflate(R.layout.list_item,null);
而context为创建Adapter时所使用的context。因此我们要在构造Adapter时,要求以context作为传参。当然,数据源保存至Adapter也是有必要的。
我们直接通过一个Demo代码来体会。
BaseAdapter Demo
(1)创建布局
<?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="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/tv_type" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:text="TextView" /> <TextView android:id="@+id/tv_format" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:text="TextView" /> <TextView android:id="@+id/tv_date" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_weight="1" android:text="TextView" /> <Button android:id="@+id/btn_del" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_weight="1" android:text="Button" /></LinearLayout>
(2)定义holder
public class myholder { public TextView mType; public TextView mFormat; public TextView mDate; public Button mDel;}
(3)组织数据源
private List<Map<String,Object>> getMyBaseAdapterViewListData(){ List<Map<String, Object>> list=new ArrayList<Map<String, Object>>(); Map<String, Object> item1=new HashMap<String, Object>(); item1.put("type","Type1"); item1.put("format","format1"); item1.put("date","date1"); list.add(item1); ... Map<String, Object> itemN=new HashMap<String, Object>(); itemN.put("type","TypeN"); itemN.put("format","formatN"); itemN.put("date","dateN"); list.add(itemN); return list; }
(4)创建BaseAdapter扩展类
public class MyAdapter extends BaseAdapter { private final String TAG=getClass().getName(); private Context mContext; private List<Map<String, Object>> mdata; public MyAdapter(Context context, List<Map<String, Object>> data){ mContext=context; mdata=data; } @Override public int getCount() { return mdata!=null?mdata.size():0; } @Override public Object getItem(int i) { return mdata!=null?mdata.get(i):null; } @Override public long getItemId(int i) { return 0; } @Override public View getView(final int i, View view, ViewGroup viewGroup) { myholder holder=new myholder(); if(view==null){ view= LayoutInflater.from(mContext).inflate(R.layout.mybaseadapterlistviewitem,null); holder.mType=(TextView) view.findViewById(R.id.tv_type); holder.mFormat=(TextView) view.findViewById(R.id.tv_format); holder.mDate=(TextView) view.findViewById(R.id.tv_date); holder.mDel=(Button) view.findViewById(R.id.btn_del); holder.mDel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Log.i(TAG, "onClick: delete "+i); mdata.remove(i); notifyDataSetInvalidated(); } }); view.setTag(holder); }else { holder=(myholder) view.getTag(); } holder.mType.setText(mdata.get(i).get("type").toString()); holder.mFormat.setText(mdata.get(i).get("format").toString()); holder.mDate.setText(mdata.get(i).get("date").toString()); holder.mDel.setText("delete"); return view; }}
这里需要注意的是,在更新数据源后,一定要调用notifyDataSetInvalidated()方法,通知ListView更新显示!
当然,对于BaseAdapter扩展类的设计可以根据自己的需求随意,例如使用回调函数传入监听函数,加入dialog提示框等。
至此,ListView的基本使用总结完毕。
- Android ListView基本使用
- 【Android 开发教程】ListView的基本使用
- (Android review)ListView的基本使用
- android学习之ListView的基本使用
- Android基本控件ListView的使用总结
- [android]_[ListView的基本使用]
- android ListView基本用法
- Listview 的基本使用
- listview的基本使用
- ListView 基本使用
- ListView基本使用
- ListView基本使用
- ListView基本使用
- ListView基本使用
- Android ListView 最基本的用法,使用SimpleCursorAdapter 。 附例子。
- Android ListView 最基本的用法,使用SimpleCursorAdapter
- Android中ListView的基本使用与优化
- Android 入门ListView 的基本使用,BaseAdapter的编写
- ARM汇编指令集1--需要的基础知识
- 知识点汇总
- C++ 基本语法
- EJB 概念
- Kubernetes之蓝绿部署
- Android ListView基本使用
- 【Angular2】CheckBox获取值的两种方式
- 求助贴
- leetcode题解之Longest Substring Without Repeating Characters
- 【操作系统】第二章小结
- Android模拟器Genymotion安装使用教程详解
- jQuery 事件
- 1499 图
- c#获取屏幕上某坐标点的颜色