Android 適配器教程 (六)
我們的適配器學習已經接近尾聲了,雖然這不是一個大問題,但是確實是值得學習的一塊知識,回想一下之前五講的知識,我們已經學到了很多東西了。
在之前五講中,我們已經由淺入深的認識了適配器,從最簡單的ListView寫起,最後完成了自定義適配器的簡單例子,然後又為大家講解了ViewHolder和settag在自定義適配器中的應用,幫助大家理解了getView方法,還講解了關於ListView性能方麵的優化問題。自定義適配器這一部分是我們這次學習真正的重點,很多問題可以用安卓原生適配器進行解決,但是也有很多問題必須通過自定義適配器才能合適的解決。
在第四講我已經提到過了,關於自定義適配器,我們將有兩個例子,一個簡單一點,一個稍微難一點,今天我們這個例子,也是最後一個例子是一個比較繁瑣的項目,希望大家認真學習,並從中領悟到知識,真正學通安卓適配器。
好的,先介紹一下今天要做的例子,大家都知道Listview和GridView,這兩個都是安卓開發中常用的控件,今天我們要把他們兩個結合在一起,使用listView嵌套GridView,形成一種可以存放多張圖片的UI設計,Google+android客戶端就是這個樣子,是不是感到有一點小繁瑣,不過沒事,我會一步步的按照寫代碼的思路講解的。
說明一下,我還是會在之前幾講的Demo上繼續添加,這次寫完我就把源碼雙手奉上了哦,看過前幾篇的讀者就比較熟悉了。
好的,現在開始動手寫吧:
項目開始:
(1)也還是先在activity_main.xml裏添加一個button,一會跳轉的時候使用。
(2)然後新建一個類FinalDemo繼承自Activity作為我們第四個個例子的Activity,@Override我們的onCreate方法。
(3)新建一個xml文件finaldemo.xml作為我們的布局文件,其中也是包含一個文本域和一個ListView:
代碼如下:
finaldemo.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:andro android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="這是ListView與GridView嵌套的一個例子" > </TextView> <ListView android: android:layout_width="wrap_content" android:layout_height="wrap_content" > </ListView> </LinearLayout>
(4)然後需要定義好一個用來顯示每一個列內容的xml文件Listitem3.xml,Listitem3.xml 包含橫向的一個圖片還有一個Gridview,Gridview的橫向滾動的實現布局主要是把gridview嵌套在HorizontalScrollView裏麵,GridView的一些屬性還要在java代碼中實現,一會大家看源碼就明白了。
Listitem3.xml:
代碼如下:
<span ><?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:andro android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <ImageView android: android:layout_width="150px" android:layout_height="150px" android:scaleType="fitXY" /> <HorizontalScrollView android: android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@null" android:scrollbars="none" > <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > <GridView android: android:layout_width="fill_parent" android:layout_height="wrap_content" android:background="@null" > </GridView> </LinearLayout> </HorizontalScrollView> </LinearLayout></span>
(5)然後需要定義好一個用來顯示橫向GridView每一個內容的gridview_item.xml,內容是一個ImageView和一個textview,
代碼如下:
gridview_item.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:andro android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <ImageView android: android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android: android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout>
(6)然後是寫出GridView的適配器:這裏在第四講講已經很詳細的說過了,我就不再多費口舌了,有什麼問題還請大家再回去看看吧:
新建一個類GridViewAdapter extends BaseAdapter,之後重寫方法就Ok了~
以下是該類的完整代碼:
package com.example.adapterdemo; import java.util.List; import java.util.Map; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.ImageView; import android.widget.TextView; public class GridViewAdapter extends BaseAdapter { private LayoutInflater mInflater; private List<Map<String, Object>> Griddata; // 構造器,接收數據 public GridViewAdapter(Context context, List<Map<String, Object>> Griddata) { this.mInflater = LayoutInflater.from(context); this.Griddata = Griddata; } @Override public int getCount() { return Griddata == null ? 0 : Griddata.size(); } @Override public Object getItem(int position) { return Griddata.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { holder = new ViewHolder(); convertView = mInflater.inflate(R.layout.gridview_item, null); holder.Gridimg = (ImageView) convertView.findViewById(R.id.Grid_iv); holder.Gridtext = (TextView) convertView.findViewById(R.id.Grid_tv); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.Gridimg.setBackgroundResource((Integer) Griddata.get(position) .get("Gridimg")); holder.Gridtext .setText((String) Griddata.get(position).get("Gridtext")); return convertView; } public final class ViewHolder { public ImageView Gridimg; public TextView Gridtext; } }
(7)然後是寫出LIstView的適配器:這裏在第四講講已經很詳細的說過了,我同樣也是就不再多費口舌了,有什麼問題還請大家再回去看看吧:
新建一個類FinalDemoListAdapter extends BaseAdapter,之後重寫方法就Ok了~
其中需要注意的就有 1.構造器部分需要分兩部分得到ListView和GridView的數據。
2.原來加載數據的部分,由於我們裏麵還嵌套了一層ListView,所以除了加載了一張 圖片,還需要加載一個GridView,並且把外部獲得的給GridView的數據傳給下一層。
3.GridView的布局設置,這裏我就不多說了,有問題的話穀歌一下就明白了。
另外我這麼寫思路比較清楚,但是效率就不敢保證了,還希望大家多多指教。
下麵給出源碼:
package com.example.adapterdemo; import java.util.List; import java.util.Map; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout.LayoutParams; import android.widget.BaseAdapter; import android.widget.GridView; import android.widget.ImageView; public class FinalDemoListAdapter extends BaseAdapter { //列寬 private int cWidth = 120; //水平間距 private int hSpacing = 10; private LayoutInflater mInflater; private List<Map<String, Object>> Listdata; private List<Map<String, Object>> Griddata; private Context context; // 構造器,接收數據 public FinalDemoListAdapter(Context context, List<Map<String, Object>> Listdata, List<Map<String, Object>> Griddata) { this.context = context; this.mInflater = LayoutInflater.from(context); this.Listdata = Listdata; this.Griddata = Griddata; } @Override public int getCount() { return Listdata == null ? 0 : Listdata.size(); } @Override public Object getItem(int position) { return Listdata.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { holder = new ViewHolder(); convertView = mInflater.inflate(R.layout.listitem3, null); holder.Listimg = (ImageView) convertView.findViewById(R.id.list_iv); holder.gridview = (GridView) convertView .findViewById(R.id.gridview); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } // 加載數據 holder.Listimg.setBackgroundResource((Integer) Listdata.get(position) .get("Listimg")); // 加載Gridview GridViewAdapter ga = new GridViewAdapter(context, Griddata); int i = ga.getCount(); LayoutParams params = new LayoutParams(i * (115 + 10), LayoutParams.WRAP_CONTENT); holder.gridview.setLayoutParams(params); holder.gridview.setColumnWidth(cWidth); holder.gridview.setHorizontalSpacing(hSpacing); holder.gridview.setStretchMode(GridView.NO_STRETCH); holder.gridview.setNumColumns(i); holder.gridview.setAdapter(ga); return convertView; } public final class ViewHolder { public ImageView Listimg; public GridView gridview; } }
(8)之後我們再回到FinalDem像之前那樣增加適配器,添加數據就好了:
我從網上下了點頭像。。。後麵的安卓機器人圖片是示例。
下麵是源碼:
package com.example.adapterdemo; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import android.app.Activity; import android.os.Bundle; import android.widget.ListView; public class FinalDemo extends Activity { private ListView lv; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.finaldemo); lv = (ListView) findViewById(R.id.finaldemolistview); FinalDemoListAdapter myadapter = new FinalDemoListAdapter(this, getListData(), getGridData()); lv.setAdapter(myadapter); } private List<Map<String, Object>> getListData() { List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); Map<String, Object> map = new HashMap<String, Object>(); map.put("Listimg", R.drawable.head1); list.add(map); map = new HashMap<String, Object>(); map.put("Listimg", R.drawable.head2); list.add(map); map = new HashMap<String, Object>(); map.put("Listimg", R.drawable.head4); list.add(map); map = new HashMap<String, Object>(); map.put("Listimg", R.drawable.head5); list.add(map); map = new HashMap<String, Object>(); map.put("Listimg", R.drawable.head6); list.add(map); map = new HashMap<String, Object>(); map.put("Listimg", R.drawable.head7); list.add(map); map = new HashMap<String, Object>(); map.put("Listimg", R.drawable.head8); list.add(map); map = new HashMap<String, Object>(); map.put("Listimg", R.drawable.head9); list.add(map); map = new HashMap<String, Object>(); map.put("Listimg", R.drawable.head10); list.add(map); map = new HashMap<String, Object>(); map.put("Listimg", R.drawable.head11); list.add(map); map = new HashMap<String, Object>(); map.put("Listimg", R.drawable.head12); list.add(map); map = new HashMap<String, Object>(); map.put("Listimg", R.drawable.head13); list.add(map); return list; } private List<Map<String, Object>> getGridData() { List<Map<String, Object>> list = new ArrayList<Map<String, Object>>(); Map<String, Object> map = new HashMap<String, Object>(); map.put("Gridimg", R.drawable.ic_launcher); map.put("Gridtext", "info 1"); list.add(map); map = new HashMap<String, Object>(); map.put("Gridimg", R.drawable.ic_launcher); map.put("Gridtext", "info 2"); list.add(map); map = new HashMap<String, Object>(); map.put("Gridimg", R.drawable.ic_launcher); map.put("Gridtext", "info 3"); list.add(map); map = new HashMap<String, Object>(); map.put("Gridimg", R.drawable.ic_launcher); map.put("Gridtext", "info 4"); list.add(map); map = new HashMap<String, Object>(); map.put("Gridimg", R.drawable.ic_launcher); map.put("Gridtext", "info 5"); list.add(map); map = new HashMap<String, Object>(); map.put("Gridimg", R.drawable.ic_launcher); map.put("Gridtext", "info 6"); list.add(map); map = new HashMap<String, Object>(); map.put("Gridimg", R.drawable.ic_launcher); map.put("Gridtext", "info 7"); list.add(map); map = new HashMap<String, Object>(); map.put("Gridimg", R.drawable.ic_launcher); map.put("Gridtext", "info 8"); list.add(map); map = new HashMap<String, Object>(); map.put("Gridimg", R.drawable.ic_launcher); map.put("Gridtext", "info 9"); list.add(map); return list; } }
到此為止就搞定了!,讓我們再看一下實現效果:
為了能看出效果,我把橫向的Gridview拉動了一下,所以是對不齊的,這裏我橫向的部分設置的底色為透明,如果在加一張背景圖片的話,相信效果會不錯的,這隻是一個Demo,在調整一下間距和尺寸,我想效果會好很多,嗬嗬~
這樣我們的教程就算是徹底結束了,希望大家能從中學到些東西就好了,這樣我的Demo程序也一並寫完了,源碼地址我會附在文章的最後~
差點忘了我還沒給大家activity_main.xml和MainActivity的源碼,這裏也再貼一下吧:
MainActivity:
package com.example.adapterdemo; import android.os.Bundle; import android.app.Activity; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.content.DialogInterface; import android.content.Intent; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; public class MainActivity extends Activity { private Button bt_1; private Button bt_2; private Button bt_3; private Button bt_4; private Button bt_5; private Button bt_6; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bt_1=(Button)findViewById(R.id.button1); bt_2=(Button)findViewById(R.id.button2); bt_3=(Button)findViewById(R.id.button3); bt_4=(Button)findViewById(R.id.button4); bt_5=(Button)findViewById(R.id.button5); bt_6=(Button)findViewById(R.id.button6); bt_1.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { Intent dataIntent = new Intent(MainActivity.this,ArrayAdapterDemo.class); startActivity(dataIntent); } }); bt_2.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { Intent dataIntent = new Intent(MainActivity.this,SimpleCursorAdapterDemo.class); startActivity(dataIntent); } }); bt_3.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { Intent dataIntent = new Intent(MainActivity.this,SimpleAdapterDemo.class); startActivity(dataIntent); } }); bt_4.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { Intent dataIntent = new Intent(MainActivity.this,MyAdapterDemo.class); startActivity(dataIntent); } }); bt_5.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { Intent dataIntent = new Intent(MainActivity.this,FinalDemo.class); startActivity(dataIntent); } }); bt_6.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { aboutWarn(); } }); } private void aboutWarn(){ AlertDialog.Builder builder = new Builder(this); builder.setMessage("這是關於學習適配器的一個例子\n作者MingChao Sun\n相關教程請訪問:\nhttps://blog.csdn.net/sunmc1204953974"); builder.setTitle("關於"); builder.setPositiveButton("確定", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); builder.setNegativeButton("取消", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); builder.create().show(); } }
activity_main.xml:
<RelativeLayout xmlns:andro xmlns:tools="https://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <Button android: android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_below="@+id/button1" android:layout_marginTop="27dp" android:text="SimpleCursorAdapterDemo" /> <Button android: android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_below="@+id/button4" android:layout_marginTop="26dp" android:text="ListView與GridView嵌套的Demo" /> <Button android: android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:text="關於" /> <Button android: android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignLeft="@+id/button2" android:layout_below="@+id/button6" android:layout_marginTop="20dp" android:text="ArrayAdapterDemo" /> <Button android: android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/button2" android:layout_marginTop="18dp" android:text="SimpleAdapterDemo" /> <Button android: android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_below="@+id/button3" android:layout_marginTop="25dp" android:text="MyAdapterDemo" /> </RelativeLayout>
好了,這就算是徹底結束了,希望大家有所所收獲!
我也是學生,水平有限,還請大家多多指教!
另外請大家尊重原創,轉載請付上我文章的地址哦~謝謝~
源碼的地址:
(一個實例徹底學會適配器)AdapterDemo.zip:
最後更新:2017-04-03 05:39:35