ListView는 안드로이드 개발에서 흔히 사용되는 컴포넌트로, 특정 내용을 목록 형태로 표시하며, 데이터 길이에 따라 적응적으로 표시할 수 있습니다. ListView의 사용법을 정리하는 시간을 갖고 아래와 같이 작은 예제를 작성했습니다.
목록 표시에는 세 가지 요소가 필요합니다.
1. 목록을 표시하는 데 사용되는 ListVeiw 보기입니다.
2. 어댑터는 ListView의 중재자에 데이터를 매핑하는 데 사용됩니다.
3. 데이터 매핑될 특정 문자열, 이미지 또는 기본 구성 요소입니다.
가장 간단한 ListView부터 시작합니다.
위 코드는 ArrayAdapter(Context context, int textViewResourceId, List<.>
/** * @author allin * */ public class MyListView extends Activity { private ListView listView; //private List<String> data = new ArrayList<String>(); @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); listView = new ListView(this); listView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1,getData())); setContentView(listView); } private List<String> getData(){ List<String> data = new ArrayList<String>(); data.add("测试数据1"); data.add("测试数据2"); data.add("测试数据3"); data.add("测试数据4"); return data; } }
SimpleCursorAdapter
SDK에 대한 설명은 다음과 같습니다. XML 파일에 정의된 TextView 또는 ImageView에 커서를 놓고 원하는 열, 표시하려는 보기 및 이러한 보기의 모양을 정의하는 XML 파일을 지정할 수 있습니다. 간단히 말해서 데이터를 표시하는 것이 편리합니다. 목록의 커서에서 가져오고 지정된 열을 해당 TextView에 매핑합니다.
다음 프로그램은 전화번호부의 연락처를 클래스 테이블에 표시합니다. 그런 다음 데이터베이스를 가리키는 커서를 얻고 레이아웃 파일을 정의합니다. (물론 시스템과 함께 제공되는 커서 커서 = getContentResolver().query를 사용할 수도 있습니다. (People.CONTENT_URI, null, null, null, null); 먼저 시스템 주소록 데이터베이스에 대한 포인터를 가져옵니다. startManagingCursor(cursor)를 가져옵니다. 활동 관리에 객체를 지정하면 커서와 활동의 라이프사이클이 자동으로 동기화되므로 수동으로 커서를 관리할 필요가 없습니다. SimpleCursorAdapter 생성자의 처음 세 매개변수는 ArrayAdapter의 매개변수와 동일합니다. 마지막 두 매개변수는 데이터베이스의 열을 포함하는 문자열 배열과 레이아웃의 해당 구성 요소 ID를 포함하는 int 배열입니다. 파일. 그 기능은 문자열 배열로 표시되는 데이터의 각 열을 레이아웃 파일의 해당 ID가 있는 구성 요소에 자동으로 매핑하는 것입니다. 위 코드는 NAME 열의 데이터를 레이아웃 파일의 ID가 text1인 구성 요소에 매핑합니다. 참고: AndroidManifest.xml에 필요한 권한:/** * @author allin * */ public class MyListView2 extends Activity { private ListView listView; //private List<String> data = new ArrayList<String>(); @Override public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); listView = new ListView(this); Cursor cursor = getContentResolver().query(People.CONTENT_URI, null, null, null, null); startManagingCursor(cursor); ListAdapter listAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_expandable_list_item_1, cursor, new String[]{People.NAME}, new int[]{android.R.id.text1}); listView.setAdapter(listAdapter); setContentView(listView); } }
효과 실행 후
SimpleAdaptersimpleAdapter는 확장성이 가장 뛰어나며 다양한 레이아웃을 정의하고 ImageView(그림)를 넣을 수 있으며 Button( 버튼), CheckBox(체크박스) 등 다음 코드는 ListActivity를 직접 상속합니다. ListActivity는 표시 측면에서 ListView를 표시하기 위해 많은 최적화가 이루어졌다는 점만 다릅니다. 다음 프로그램은 그림이 있는 수업 테이블을 구현합니다.먼저 각 열의 내용을 표시하는 xml을 정의해야 합니다
vlist.xml
다음은 구현 코드입니다.simpleAdapter에서 사용하는 데이터는 일반적으로 HashMap으로 구성된 List입니다. 목록의 각 섹션은 ListView의 각 행에 해당합니다. HashMap의 각 키-값 데이터는 레이아웃 파일의 해당 ID를 가진 구성 요소에 매핑됩니다. 시스템에는 사용 가능한 해당 레이아웃 파일이 없기 때문에 vlist.xml 레이아웃을 직접 정의할 수 있습니다. 다음으로, 새로운 SimpleAdapter의 매개변수는 레이아웃 파일(vlist.xml), HashMap의 제목 및 정보, img입니다. 레이아웃 파일의 구성 요소 ID, 제목, 정보, img입니다. 레이아웃 파일의 각 구성 요소는 HashMap의 각 요소에 매핑되어 적응을 완료합니다.
작동 효과는 다음과 같습니다.
有按钮的ListView
但是有时候,列表不光会用来做显示用,我们同样可以在在上面添加按钮。添加按钮首先要写一个有按钮的xml文件,然后自然会想到用上面的方法定义一个适配器,然后将数据映射到布局文件上。但是事实并非这样,因为按钮是无法映射的,即使你成功的用布局文件显示出了按钮也无法添加按钮的响应,这时就要研究一下ListView是如何现实的了,而且必须要重写一个类继承BaseAdapter。下面的示例将显示一个按钮和一个图片,两行字如果单击按钮将删除此按钮的所在行。并告诉你ListView究竟是如何工作的。效果如下:
vlist2.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent"> <ImageView android:id="@+id/img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="5px"/> <LinearLayout android:orientation="vertical" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#FFFFFFFF" android:textSize="22px" /> <TextView android:id="@+id/info" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#FFFFFFFF" android:textSize="13px" /> </LinearLayout> <Button android:id="@+id/view_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/s_view_btn" android:layout_gravity="bottom|right" /> </LinearLayout>
程序代码:
/** * @author allin * */ public class MyListView4 extends ListActivity { private List<Map<String, Object>> mData; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mData = getData(); MyAdapter adapter = new MyAdapter(this); setListAdapter(adapter); } private List<Map<String, Object>> getData() { List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); Map<String, Object> map = new HashMap<String, Object>(); map.put("title", "G1"); map.put("info", "google 1"); map.put("img", R.drawable.i1); list.add(map); map = new HashMap<String, Object>(); map.put("title", "G2"); map.put("info", "google 2"); map.put("img", R.drawable.i2); list.add(map); map = new HashMap<String, Object>(); map.put("title", "G3"); map.put("info", "google 3"); map.put("img", R.drawable.i3); list.add(map); return list; } // ListView 中某项被选中后的逻辑 @Override protected void onListItemClick(ListView l, View v, int position, long id) { Log.v("MyListView4-click", (String)mData.get(position).get("title")); } /** * listview中点击按键弹出对话框 */ public void showInfo(){ new AlertDialog.Builder(this) .setTitle("我的listview") .setMessage("介绍...") .setPositiveButton("确定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { } }) .show(); } public final class ViewHolder{ public ImageView img; public TextView title; public TextView info; public Button viewBtn; } public class MyAdapter extends BaseAdapter{ private LayoutInflater mInflater; public MyAdapter(Context context){ this.mInflater = LayoutInflater.from(context); } @Override public int getCount() { // TODO Auto-generated method stub return mData.size(); } @Override public Object getItem(int arg0) { // TODO Auto-generated method stub return null; } @Override public long getItemId(int arg0) { // TODO Auto-generated method stub return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { holder=new ViewHolder(); convertView = mInflater.inflate(R.layout.vlist2, null); holder.img = (ImageView)convertView.findViewById(R.id.img); holder.title = (TextView)convertView.findViewById(R.id.title); holder.info = (TextView)convertView.findViewById(R.id.info); holder.viewBtn = (Button)convertView.findViewById(R.id.view_btn); convertView.setTag(holder); }else { holder = (ViewHolder)convertView.getTag(); } holder.img.setBackgroundResource((Integer)mData.get(position).get("img")); holder.title.setText((String)mData.get(position).get("title")); holder.info.setText((String)mData.get(position).get("info")); holder.viewBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { showInfo(); } }); return convertView; } } }
下面将对上述代码,做详细的解释,listView在开始绘制的时候,系统首先调用getCount()函数,根据他的返回值得到listView的长度(这也是为什么在开始的第一张图特别的标出列表长度),然后根据这个长度,调用getView()逐一绘制每一行。如果你的getCount()返回值是0的话,列表将不显示同样return 1,就只显示一行。
系统显示列表时,首先实例化一个适配器(这里将实例化自定义的适配器)。当手动完成适配时,必须手动映射数据,这需要重写getView()方法。系统在绘制列表的每一行的时候将调用此方法。getView()有三个参数,position表示将显示的是第几行,covertView是从布局文件中inflate来的布局。我们用LayoutInflater的方法将定义好的vlist2.xml文件提取成View实例用来显示。然后将xml文件中的各个组件实例化(简单的findViewById()方法)。这样便可以将数据对应到各个组件上了。但是按钮为了响应点击事件,需要为它添加点击监听器,这样就能捕获点击事件。至此一个自定义的listView就完成了,现在让我们回过头从新审视这个过程。系统要绘制ListView了,他首先获得要绘制的这个列表的长度,然后开始绘制第一行,怎么绘制呢?调用getView()函数。在这个函数里面首先获得一个View(实际上是一个ViewGroup),然后再实例并设置各个组件,显示之。好了,绘制完这一行了。那 再绘制下一行,直到绘完为止。在实际的运行过程中会发现listView的每一行没有焦点了,这是因为Button抢夺了listView的焦点,只要布局文件中将Button设置为没有焦点就OK了。
运行效果如下图: