學徒淺析Android開發:第二講——ListView和GridView的應用

                本講的核心是向大家介紹如何通過自定義適配器來應用到ListView和GridView上,並介紹ListView和GridView的常用方法。

               作爲最常使用的兩種控件,ListView  和GridView廣泛出現在各種APP中,最常見的就是電話薄和九宮格,Android自身也提供了相應的適配器比如SimpleAdapter,但往往我們在開發過程中對於列表項有更高的要求,此時SimpleAdapter便不能勝任了,同時SimpleAdapter的書寫過於繁瑣,對比一下就知道:

               // 使用simpleAdapter封裝數據,將圖片顯示出來,此時的適配器沒有監聽功能
               // 參數一是當前上下文Context對象
               // 參數二是圖片數據列表,要顯示數據都在其中
               // 參數三是界面的XML文件,注意,不是整體界面,而是要顯示在GridView中的單個Item的界面XML
               // 參數四是動態數組中與map中圖片對應的項,也就是map中存儲進去的相對應於圖片value的key
              // 參數五是單個Item界面XML中的圖片ID
             SimpleAdapter simpleAdapter = new SimpleAdapter(this, imagelist, R.layout.items, new String[] { "image", "text" }, new int[] {R.id.image, R.id.title });
             gridview.setAdapter(simpleAdapter);

               // 使用自定義的DownAdapter封裝數據,此時的適配器有監聽功能
               // 參數一是當前上下文Context對象
               // 參數二是列表項數據列表,一個列表項要顯示的數據都在其中
               // 參數三是當前要使用該適配器的視圖

             DownAdapter downadapter = new DownAdapter(this,list,girdview);

              gridview.setAdapter(downadapter);
            怎麼樣,差距是不是很明顯,沒有人喜歡這麼長的輸入方式,除非你是女的。

            好了,不說廢話了,下面就是我們今天用到的代碼,具體的解釋都寫在裏面了,有疑問的可以留言。

            首先我們西安家裏兩個包,分別分裝ListView和GirdView的項目格式。這個格式隨你而變。

        

相應的我們重建一下第一講中的view_first.xml

<?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="vertical" >
    <!-- @author Arthur Lee -->
    <!-- 垂直分佈兩個,以AB標記 -->
    <!-- A -->
    <LinearLayout 
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="4"
        android:gravity="center_vertical|center_horizontal">
        <TextView
          android:id="@+id/view_first"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:text="第一頁面"
          android:textSize="20sp" />
    </LinearLayout>
    <!-- A -->
    <LinearLayout 
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:orientation="horizontal">
        <!-- 水平分佈兩個,一12標記 -->
        <!-- 1 -->
        <LinearLayout 
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_weight="4">
            <!-- 提示欄 -->
            <TextView 
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center"
                android:text="上欄是ListView,下欄是GridView"
                android:textSize="20sp"/>
        </LinearLayout>
        <!-- 2 -->
        <LinearLayout 
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:layout_weight="1">
            <!-- 垂直分佈兩個,以ab標記 -->
            <!-- a -->
             <LinearLayout 
                 android:id="@+id/firist_upview"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:layout_weight="1">
            <!-- ListView展示區 -->
            <ListView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/first_up"></ListView>
            </LinearLayout>
            <!-- b -->
             <LinearLayout 
                 android:id="@+id/firist_downview"
                 android:layout_width="match_parent"
                 android:layout_height="match_parent"
                 android:layout_weight="1">
            <!-- GridView展示區 -->
            <GridView 
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/first_down"
                android:horizontalSpacing="5dp"
                android:verticalSpacing="5dp"
                android:stretchMode="columnWidth"
                android:columnWidth="90dp"
                android:numColumns="4" ></GridView>
            </LinearLayout>
        </LinearLayout>
        
    </LinearLayout>
   

</LinearLayout>

package com.teach.up;
/**
 * @author Arthur Lee
 * @time 04/12/2014
 * */
//Up是一個角色類,也可以把它寫成一個內部類,用它來封裝列表項的數據,既方便有美觀。
public class Up {
	//自定義的參數
	private String strName;
	private String strNum;
	
	public Up(String strName, String strNum) {
		super();
		this.strName = strName;
		this.strNum = strNum;
	}
	//我們需要爲這個角色類設置get和set方法,以便於獲取和傳遞數據
	public String getStrName() {
		return strName;
	}
	public void setStrName(String strName) {
		this.strName = strName;
	}
	public String getStrNum() {
		return strNum;
	}
	public void setStrNum(String strNum) {
		this.strNum = strNum;
	}
}

package com.teach.up;
/**
 * @author Arthur Lee
 * @time 04/12/2014
 * */
import java.util.ArrayList;
import java.util.List;

public class UpSerivce {
	/**
	 * 在這個服務類裏,我只定義了一個getString方法來獲得列表項數據,大家可以在這裏對數據進行封裝處理。
	 * 盡你所能,我在這裏就偷懶了,大家不要學我啊,
	 * by the way,這個服務類可有可無,我這樣單獨建一個類主要是爲了方便大家學習。只要有getString這個方法就行
	 * @param 這裏的參數可以是任何形式,對於客戶端的開發來說,最常用的就是JSON格式。這個我會在第七講中詳細介紹JSON格式
	 * @return 直接返回我們封裝好的數據隊列
	 */
	public static List<Up> getString(int count){
		List<Up> up = new ArrayList<Up>();
		for(int i=0;i<count;i++)
		    up.add(new Up("觀衆"+i+"號","按鍵"+i+"號"));
		return up;
	}

}

package com.teach.up;
/**
 * @author Arthur Lee
 * @time 04/12/2014
 * */
import java.util.List;

import com.teach.demo.R;

import android.content.Context;
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;
import android.widget.Toast;

public class UpAdapter extends BaseAdapter{

	private Context context;
	private LayoutInflater inflater;
	private List<Up> first;
	private ListView list;
	//設定列表項所需控件,要和自己設計 的列表項控件一致。
	//在這裏我偷懶一下,就放三個。
	static class ListItem{
		TextView tView;
		ImageView iView; 
		Button bt_click;
		Button bt_delect;
		
	}
	/**設置構造函數,對pUAdapter的內容進行綁定
	 * @param context  決定當前Actvity類
	 * @param first    所需加載啊的列表項數據
	 * @param list     當前適配器匹配的視圖類型,這裏換成GridView類型的話,顯示的列表項就會是九宮格風格
	 */
	public UpAdapter(Context context,List<Up> first,ListView list){
		this.context = context;
		//指定當前LayoutInflater服務的Activity,一遍後面初始化相應的視圖。
		this.inflater = LayoutInflater.from(context);
		this.list = list;
		this.first = first;
	}

	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return first.size();
	}

	@Override
	public Object getItem(int position) {
		// TODO Auto-generated method stub
		return first.get(position);
	}

	@Override
	public long getItemId(int arg0) {
		// TODO Auto-generated method stub
		return 0;
	}

	/**
	 * @param position  指定列表項的當前所處位置
	 * @param view      指定視圖,即當前列表項
	 * @param parents   指定視圖所屬的父類,即當前列表項所屬的列表
	 * 
	 * 此處是Adapter的關鍵所在,任何視圖在配置Adapter時,
	 * 都是通過調用Adapter的getView方法,將視圖中所需的每個小項組裝成定義後的樣子。
	 */
	@Override
	public View getView(final int position, View view, ViewGroup parents) {
		// TODO Auto-generated method stub
		ListItem item = null;
		//如果當前爲空,則對視圖進行初始化
		if(view == null){
			//指定當前視圖所對應xml文件。並初始化其中的控件,這個view就是一個小的列表項
			view = inflater.inflate(R.layout.view_first_upitem, null);
			item = new ListItem();
			item.iView = (ImageView)view.findViewById(R.id.first_photo);
			item.bt_click = (Button)view.findViewById(R.id.first_click);
			item.bt_delect = (Button)view.findViewById(R.id.first_delect);
			item.tView = (TextView)view.findViewById(R.id.first_name);
			//當且視圖控件指向item,即完成綁定
			view.setTag(item);
		}else{
			//若當前視圖不爲空,那麼直接從當前view中綁定控件,以便執行相應操作。
			item = (ListItem)view.getTag();
		}
		/**我可可以在這裏執行響應的頁面操作,比如賦值,刪除,點擊事件等
		 * 下面我會一一舉個小例子
		 */
		/**
		 * 賦值
		 * 這裏的數據可以是從本地數據庫中,服務端,網絡,或者是程序自動生成的
		 * 
		 */
		 Up up = first.get(position);
		 item.tView.setText(up.getStrName());
		 item.iView.setImageResource(R.drawable.ic_launcher);
		 item.bt_delect.setText("刪除");
		 item.bt_click.setText(up.getStrNum());
		 /**
		  * 添加監聽
		  * 在開發過程中,一般爲了方便起見,都是將監聽操作寫在Adapter裏面,主要是方便,你也可以在外部通過OnItemClickListener對視圖註冊監聽
		  * */
		 item.bt_click.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				// TODO Auto-generated method stub
				//我在這讓輸出一個提示,打擊可以在這裏進行任何操作。
				Toast.makeText(context, "你選擇了"+position, Toast.LENGTH_LONG).show();
			}
		});
		 /**
		  * 刪除
		  * 對於LsitView和GridView操作,刪除操作常用的事,而BaseAdapter也提供給我們兩種刪除的反饋機制
		  * 分別是notifyDataSetInvalidated()和notifyDataSetChanged()
		  * 這兩個方法可以直接使用,也可以對他們進行重寫,在這裏我就不重寫了
		  * 他們的區別是出發後的機制不同
		  * notifyDataSetChanged():重繪當前可見區域,它是通過調用getView來刷新
		  * notifyDataSetInvalidated():重繪控件,他是通過在內部調用onChanged事件
		  * */
		item.bt_delect.setOnClickListener(new OnClickListener() {
				
				@Override
				public void onClick(View arg0) {
					// TODO Auto-generated method stub
					first.remove(position);
					notifyDataSetChanged();
				}
			});
		return view;
	}
	//想重寫的話,在這裏添加內容即可
	@Override
	public void notifyDataSetChanged() {
		// TODO Auto-generated method stub
		super.notifyDataSetChanged();
	}

}
package com.teach.down;

import java.util.ArrayList;
import java.util.List;

public class Down {

	private String strName;

	public Down(String strName) {
		super();
		this.strName = strName;
	}

	public String getStrName() {
		return strName;
	}

	public void setStrName(String strName) {
		this.strName = strName;
	}
	
	public static List<Down> getString (int count){
		List<Down> down = new ArrayList<Down>();
		for(int i=0;i<count;i++)
			down.add(new Down("男"+i+"號"));
		return down;
	}
}

package com.teach.down;
/**
 * @author Arthur Lee
 * @time 04/12/2014
 * */
import java.util.List;

import com.teach.demo.R;
import com.teach.up.Up;

import android.content.Context;
import android.graphics.Color;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;

public class DownAdapter extends BaseAdapter{

	private Context context;
	private LayoutInflater inflater;
	private List<Down> first;
	private GridView grid;
	private static int selectItem;
	//設定列表項所需控件,要和自己設計 的列表項控件一致。
	//在這裏我偷懶一下,就放三個。
	static class GridItem{
		TextView tView;
		ImageView iView; 
		
	}
	/**設置構造函數,對pUAdapter的內容進行綁定
	 * @param context  決定當前Actvity類
	 * @param first    所需加載啊的列表項數據
	 * @param list     當前適配器匹配的視圖類型,這裏換成GridView類型的話,顯示的列表項就會是九宮格風格
	 */
	public DownAdapter(Context context,List<Down> first,GridView grid){
		this.context = context;
		//指定當前LayoutInflater服務的Activity,一遍後面初始化相應的視圖。
		this.inflater = LayoutInflater.from(context);
		this.grid = grid;
		this.first = first;
	}

	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return first.size();
	}

	@Override
	public Object getItem(int position) {
		// TODO Auto-generated method stub
		return first.get(position);
	}

	@Override
	public long getItemId(int arg0) {
		// TODO Auto-generated method stub
		return 0;
	}
   
	/**
	 * @param position  指定列表項的當前所處位置
	 * @param view      指定視圖,即當前列表項
	 * @param parents   指定視圖所屬的父類,即當前列表項所屬的列表
	 * 
	 * 此處是Adapter的關鍵所在,任何視圖在配置Adapter時,
	 * 都是通過調用Adapter的getView方法,將視圖中所需的每個小項組裝成定義後的樣子。
	 */
	@Override
	public View getView(int position, View view, ViewGroup parents) {
		// TODO Auto-generated method stub
		GridItem gitem = null;
		//如果當前爲空,則對視圖進行初始化
		if(view == null){
			//指定當前視圖所對應xml文件。並初始化其中的控件,這個view就是一個小的列表項
			view = inflater.inflate(R.layout.view_first_downitem, null);
			gitem = new GridItem();
			gitem.iView = (ImageView)view.findViewById(R.id.first_downiv);
			gitem.tView = (TextView)view.findViewById(R.id.first_downtv);
			//當且視圖控件指向item,即完成綁定
			view.setTag(gitem);
		}else{
			//若當前視圖不爲空,那麼直接從當前view中綁定控件,以便執行相應操作。
			gitem = (GridItem)view.getTag();
		}
		
	    gitem.iView.setImageResource(R.drawable.ic_launcher);
	    gitem.tView.setText(first.get(position).getStrName().toString());
	    //點擊高亮效果
	    if(position == selectItem){
	    	view.setBackgroundColor(Color.CYAN);
	    }else{
	    	view.setBackgroundColor(Color.WHITE);
	    }
		
		return view;
	}
	    //獲取當前點擊的項目位置
		public static  void getSelectItem(int select){
			selectItem = select;
		}
}


同時我們要建立兩個列表項的xml文件,在這個xml文件中你所構造的佈局,就是應用到ListView或GridView的項目格式,他們的每一項都將按照這個佈局顯示出來


這是view_first_downitem.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
     <!-- @author Arthur Lee -->
    <TextView
        android:id="@+id/first_downtv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/first_downiv"
        android:layout_below="@+id/first_downiv"
        android:text="TextView" />

    <ImageView
        android:id="@+id/first_downiv"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:src="@drawable/ic_launcher" />

</RelativeLayout>
這是view_first_upitem.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <!-- @author Arthur Lee -->
    <ImageView
        android:id="@+id/first_photo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="66dp"
        android:layout_marginTop="89dp"
        android:src="@drawable/ic_launcher" />

    <TextView
        android:id="@+id/first_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/first_photo"
        android:layout_marginLeft="14dp"
        android:layout_marginTop="14dp"
        android:layout_toRightOf="@+id/first_photo"
        android:text="TextView" />

    <Button
        android:id="@+id/first_click"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/first_photo"
        android:layout_marginLeft="27dp"
        android:layout_toRightOf="@+id/first_name"
        android:text="Button" />

    <Button
        android:id="@+id/first_delect"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBaseline="@+id/first_click"
        android:layout_alignBottom="@+id/first_click"
        android:layout_toRightOf="@+id/first_click"
        android:text="Button" />

</RelativeLayout>

下面我們就要對第一講裏的FirstFragment進行重寫

package com.teach.demo;
/**
 * @author Arthur Lee
 * @time 04/08/2014
 * */
import java.util.ArrayList;
import java.util.List;

import com.teach.down.Down;
import com.teach.down.DownAdapter;
import com.teach.up.Up;
import com.teach.up.UpAdapter;
import com.teach.up.UpSerivce;

import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
import android.widget.ListView;

public class FirstFragment extends Fragment{
	    //緩存視圖
		private View view,upview,downview;
		private Context context;
		/*
		 *ListView相關控件 */
		private List<Up> up;
		private ListView listview;
		private UpAdapter Uadapter;
		/*
		 * GridView相關控件*/
		private List<Down> down;
		private GridView gridview;
		private DownAdapter Dadapter;
		

		@Override
		public void onCreate(Bundle savedInstanceState) {
			// TODO Auto-generated method stub
			super.onCreate(savedInstanceState);
		}
	    
		@Override
		public View onCreateView(LayoutInflater inflater, ViewGroup container,
				Bundle savedInstanceState) {
			// TODO Auto-generated method stub
			//如果當前視圖爲空,初始化視圖
			if(view == null){
				//指定當前視圖在viewpager中顯示的是view_first。xml,通過LayoutInflater來指定.
				view = inflater.inflate(R.layout.view_first, container,false);
			}
			//指定當前視圖的父類,以便調用父類的移除功能。
		    ViewGroup parent = (ViewGroup) view.getParent();
		    if (parent != null) {
				parent.removeView(view);
			}
		
		    upview = (View)view.findViewById(R.id.firist_upview);
		    listview = (ListView)upview.findViewById(R.id.first_up);
		    up = new ArrayList<Up>();
		    up = UpSerivce.getString(5);
		    Uadapter = new UpAdapter(getActivity(),up,listview);
		    //此時的listview已經具有了監聽功能
		    listview.setAdapter(Uadapter);
		    
		    
		    downview = (View)view.findViewById(R.id.firist_downview);
		    gridview = (GridView)downview.findViewById(R.id.first_down);
		    down = new ArrayList<Down>();
		    down = Down.getString(5);
		    Dadapter = new DownAdapter(getActivity(),down,gridview);
		    gridview.setAdapter(Dadapter);
		    //在這裏我使用了和ListView不同的監聽註冊方法
		    gridview.setOnItemClickListener(new OnItemClickListener() {

				@Override
				public void onItemClick(AdapterView<?> arg0, View arg1,
						int position, long arg3) {
					// TODO Auto-generated method stub
					Dadapter.getSelectItem(position);
					//通知適配器控件發生變化。無需重繪視圖。
					Dadapter.notifyDataSetInvalidated();
				}
			});
		    
			return view;
		}
}


運行模擬器,效果圖如下:




還是那句話:我不是一名好的程序員,因爲我只會默默奉獻

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章