Android各類Adapter的用法
一樣是一個ListView,能夠用不一樣的java
Adapter讓它顯示出來,好比說最經常使用的ArrayAdapter,SimpleAdapter,SimpleCursorAdapter,以及重寫BaseAdapter等方法。
ArrayAdapter比較簡單,但它只能用於顯示文字。而SimpleAdapter則有很強的擴展性,能夠自定義出各類效果,SimpleCursorAdapter則能夠從數據庫中讀取數據顯示在列表上,經過從寫BaseAdapter能夠在列表上加處理的事件等。
下面先來看看ArrayAdapter:
android
package com.shang.test; import java.util.ArrayList; import android.app.Activity; import android.os.Bundle; import android.widget.ArrayAdapter; import android.widget.ListView; /** * * @author shangzhenxiang * */ public class TestArrayAdapterActivity extends Activity{ private ListView mListView; private ArrayList<String> mArrayList = new ArrayList<String>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.testarrayadapter); mListView = (ListView) findViewById(R.id.myArrayList); mListView.setAdapter(new ArrayAdapter<String>(this, android.R.layout.simple_expandable_list_item_1, getData())); } private ArrayList<String> getData() { mArrayList.add("測試數據1"); mArrayList.add("測試數據2"); mArrayList.add("測試數據3"); mArrayList.add("測試數據4"); mArrayList.add("測試數據5"); mArrayList.add("測試數據6"); return mArrayList; } }
佈局裏面有個ListView就能夠了:git
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="fill_parent"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/hello"/> <ListView android:id="@+id/myArrayList" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout>
上面的代碼中用到了ArrayAdapter的構造方法:數據庫
Api中是這麼描述的:express
其中Context爲當前的環境變量,能夠顯示一行文字的一個佈局文件,和一個List的集合,也就是數據源。apache
佈局文件能夠本身寫,也能夠用系統的,我這裏是用的系統的。本身寫的佈局中包含一個TextView就能夠了,固然系統中也有包含一個TextView的佈局文件:就是 android.R.layout.simple_expandable_list_item_1,調用這個比較方便。數組
這裏給出運行後的效果圖:app
下面說說SimpleCursorAdapter:less
Api中是這麼說的:An easy adapter to map columns from a cursor to TextViews or ImageViews defined in an XML file. You can specify which columns you want, which views you want to display the columns, and the XML file that defines the appearance of these views.ide
簡單的說就是 方便把Cursor中獲得的數據進行列表顯示,並能夠把指定的列映射到指定的TextView上。
我這裏寫的是從聯繫人中拿到數據並顯示在列表上。代碼以下:
package com.shang.test; import android.app.Activity; import android.database.Cursor; import android.os.Bundle; import android.provider.Contacts.People; import android.widget.ListView; import android.widget.SimpleCursorAdapter; /** * * @author shangzhenxiang * */ public class TestSimpleCursorAdapter extends Activity { private ListView mListView; private Cursor mCursor; private SimpleCursorAdapter mAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.testsimplecursoradapter); mListView = (ListView) findViewById(R.id.mySimpleCursorList); mCursor = getContentResolver().query(People.CONTENT_URI, null, null, null, null); startManagingCursor(mCursor); mAdapter = new SimpleCursorAdapter(TestSimpleCursorAdapter.this, android.R.layout.simple_expandable_list_item_1, mCursor, new String[]{People.NAME}, new int[]{android.R.id.text1}); mListView.setAdapter(mAdapter); } }
mCursor = getContentResolver().query(People.CONTENT_URI, null, null, null, null);是先得到一個指向系統聯繫人的Cursor
startManagingCursor(mCursor);是指咱們把Cursor交給這個Activity保管,這樣Cursor便會和Activity同步,咱們不用手動管理了。
simpleCursorAdapter API中是這樣說的:
其中前面的2個參數跟ArrayAdapter中是同樣的,第三個參數是傳個來的參數, 其實也是數據源,後面的2個參數是2個數組,前一個是String【】類型的,然後一個是int【】類型的,說明前一個參數中的值對應的是從數據庫中的字 段,後一個是佈局文件中和這個字段對應的id,也就是說這個字段對應得值要顯示在哪裏(好比說咱們這裏查到的聯繫人中的NAME字段,要顯示在一個對應的 TextView上面)。
這裏咱們具體看一下系統的佈局,也就是咱們這裏的第二個參數的佈局,便於理解,android.R.layout.simple_expandable_list_item_1.xml文件中是這麼寫的:
<?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2006 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/text1" android:layout_width="match_parent" android:layout_height="?android:attr/listPreferredItemHeight" android:paddingLeft="?android:attr/expandableListPreferredItemPaddingLeft" android:textAppearance="?android:attr/textAppearanceLarge" android:gravity="center_vertical" />
注意他有一個id,這個id也是系統的id,這個佈局中只有一個TextView,因此只能顯示一個字段,咱們這裏顯示的聯繫人的名字,
而最後的一個參數就是由這麼寫id組成的一個數據(若是有不少TextView的話)。好比說咱們要顯示不少字段,佈局文件中就要寫不少TextView,而每個TextView都有一個ID,第三個參數中有多少個字段,第四個參數中就有多少個id,並一一對應。
咱們來看一下運行效果圖:
上面說到的2種方法都是顯示的文字,比方說咱們要顯示圖片怎麼辦呢,還要顯示不少內容,還要按本身喜歡的佈局排列怎麼辦呢,用SimpleAdapter,擴展性好,能夠定義各類各樣的佈局。
代碼以下:
package com.shang.test; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import android.app.Activity; import android.os.Bundle; import android.widget.ListView; import android.widget.SimpleAdapter; /** * * @author shangzhenxiang * */ public class TestSimpleAdapter extends Activity { private ListView mListView; private SimpleAdapter mAdapter; private List<HashMap<String, Object>> mHashMaps; private HashMap<String, Object> map; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.testsimpleadapter); mListView = (ListView) findViewById(R.id.mySimpleList); mAdapter = new SimpleAdapter(this, getData(), R.layout.simpleitem, new String[]{"image", "title", "info"}, new int[]{R.id.img, R.id.title, R.id.info}); mListView.setAdapter(mAdapter); } private List<HashMap<String, Object>> getData() { mHashMaps = new ArrayList<HashMap<String,Object>>(); map = new HashMap<String, Object>(); map.put("image", R.drawable.gallery_photo_1); map.put("title", "G1"); map.put("info", "google 1"); mHashMaps.add(map); map = new HashMap<String, Object>(); map.put("image", R.drawable.gallery_photo_2); map.put("title", "G2"); map.put("info", "google 2"); mHashMaps.add(map); map = new HashMap<String, Object>(); map.put("image", R.drawable.gallery_photo_3); map.put("title", "G3"); map.put("info", "google 3"); mHashMaps.add(map); return mHashMaps; } }
simpleAdapter的數據都是用HashMap構成的List,List裏面的每一節對應的是ListView的沒一行,這裏先建一個HashMap構成的List,佈局中有3個元素,ImageView,2個TextView,每一個item項的佈局文件以下:
<?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" android:orientation="horizontal"> <ImageView android:layout_width="wrap_content" android:id="@+id/img" android:layout_margin="5px" android:layout_height="wrap_content"> </ImageView> <LinearLayout android:id="@+id/linearLayout1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#ffffff" android:textSize="22px"></TextView> <TextView android:id="@+id/info" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#ffffff" android:textSize="13px"></TextView> </LinearLayout> </LinearLayout>
因此有了HashMap構成的數組後,咱們要在HashMap中加入數據,按順序加入圖片,title,info,一個HashMap就構成了ListView中的一個Item項,咱們在看下API中是怎麼描述simpleAdapter的:
第一個參數和第三個參數跟ArrayAdapter中的是同樣的,第二個參數就是由HashMap組成的List,也就是數據源,而第5個參數也就是map中的key,最後一個參數就是map中key對應的值要顯示在佈局中的位置的id。
看下效果:
若是咱們想在每一個Item中加個button,並且點擊button有對應的操做,那該怎麼辦呢。
這時咱們能夠重寫baseAdapter,看代碼:
package com.shang.test; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.Button; import android.widget.ImageView; import android.widget.ListView; import android.widget.TextView; /** * * @author shangzhenxiang * */ public class TestBaseAdapter extends Activity { private ListView mListView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.baseadapterlist); mListView = (ListView) findViewById(R.id.baselist); mListView.setAdapter(new BaseListAdapter(this)); } private List<HashMap<String, Object>> getData() { List<HashMap<String, Object>> maps = new ArrayList<HashMap<String,Object>>(); HashMap<String, Object> map = new HashMap<String, Object>(); map.put("image", R.drawable.gallery_photo_1); map.put("title", "G1"); map.put("info", "google 1"); maps.add(map); map = new HashMap<String, Object>(); map.put("image", R.drawable.gallery_photo_2); map.put("title", "G2"); map.put("info", "google 2"); maps.add(map); map = new HashMap<String, Object>(); map.put("image", R.drawable.gallery_photo_3); map.put("title", "G3"); map.put("info", "google 3"); maps.add(map); return maps; } private class BaseListAdapter extends BaseAdapter implements OnClickListener { private Context mContext; private LayoutInflater inflater; public BaseListAdapter(Context mContext) { this.mContext = mContext; inflater = LayoutInflater.from(mContext); } @Override public int getCount() { return getData().size(); } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return 0; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder viewHolder = null; if(convertView == null) { viewHolder = new ViewHolder(); convertView = inflater.inflate(R.layout.testbaseadapter, null); viewHolder.img = (ImageView) convertView.findViewById(R.id.img); viewHolder.title = (TextView) convertView.findViewById(R.id.title); viewHolder.info = (TextView) convertView.findViewById(R.id.info); viewHolder.button = (Button) convertView.findViewById(R.id.basebutton); convertView.setTag(viewHolder); } else { viewHolder = (ViewHolder) convertView.getTag(); } System.out.println("viewHolder = " + viewHolder); viewHolder.img.setBackgroundResource((Integer) getData().get(position).get("image")); viewHolder.title.setText((CharSequence) getData().get(position).get("title")); viewHolder.info.setText((CharSequence) getData().get(position).get("info")); viewHolder.button.setOnClickListener(this); return convertView; } class ViewHolder { ImageView img; TextView title; TextView info; Button button; } @Override public void onClick(View v) { int id = v.getId(); switch(id) { case R.id.basebutton: showInfo(); break; } } private void showInfo() { new AlertDialog.Builder(TestBaseAdapter.this).setTitle("my listview").setMessage("introduce...."). setPositiveButton("OK", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub } }).show(); } } }
在看下item的佈局文件:
<?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" android:orientation="horizontal"> <ImageView android:layout_width="wrap_content" android:id="@+id/img" android:layout_margin="5px" android:layout_height="wrap_content"> </ImageView> <LinearLayout android:id="@+id/linearLayout1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#ffffff" android:textSize="22px"></TextView> <TextView android:id="@+id/info" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#ffffff" android:textSize="13px"></TextView> </LinearLayout> <Button android:id="@+id/basebutton" android:text="more" android:focusable="false" android:layout_gravity="bottom|right" android:layout_height="wrap_content" android:layout_width="wrap_content"/> </LinearLayout>
listView在開始繪製的時候,系統首先調用getCount()函數,根據他的返回值獲得listView的長度(這也是爲何在開始的第一張圖特 別的標出列表長度),而後根據這個長度,調用getView()逐一繪製每一行。若是你的getCount()返回值是0的話,列表將不顯示一樣 return 1,就只顯示一行。
若是咱們要自定義適配器,那就要重寫getView方法,getView()有三個參數,position表示將顯示的是第幾 行,covertView是從佈局文件中inflate來的佈局。咱們寫一個類來描述佈局文件中的各個組件,好比ImageView,TextView 等,而後判斷convertView是否爲空,若是爲空就從inflate中拿到佈局,並新建一個ViewHolder,而後從convertView中 拿到佈局中的各個組件,同時把ViewHolder放到tag中去,下次就不用重寫new了,直接從tag中拿就能夠了,而後把佈局中的各個組件都設上對 應的值,這裏的Position對應到含有HashMap的List中的position。
在實際的運行過程當中會發現listView的每一行沒有焦點了,這是由於Button搶奪了listView的焦點,只要佈局文件中將Button設置爲沒有焦點就OK了。
看下運行效果:
源代碼: