学徒浅析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;
		}
}


运行模拟器,效果图如下:




还是那句话:我不是一名好的程序员,因为我只会默默奉献

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值