Android自定义Listview


在Android的android.support.v4包中有个DrawerLayout布局,可以显示侧滑效果,而里面的内容则用ListView填充。

为了做得更像菜单,需要自定义ListView,参考了很多博客和论坛,效果如下:




首先在Drawerlayout布局里定义ListView组件,也可以RelativeLayout,LinearLayout等布局里定义。main.xml文件:

<ListView 
    android:id="@+id/left_drawer"
    android:layout_width="240dp"
    android:layout_height="match_parent"
    android:layout_gravity="start"
    android:background="#ffffff"
    android:choiceMode="singleChoice"
    android:divider="#55aaaaaa"
    android:dividerHeight="1dp"
        ></ListView>


android:layout_gravity="start"是和Drawerlayout布局一起使用时的属性,这里可以暂时忽略

android:choiceMode="singleChoice"是单选模式,即每次只能点击一个

dividerHeight和divider分别是分割线的高度和颜色,dividerHeight设置为0时可以不显示分割线


由于要自定义ListView,所以还要为ListView里的每一项定义同一个布局list_item.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="horizontal" >
    
    <ImageView 
        android:id="@+id/drawer_list_image"
		android:layout_width="50dp"
		android:layout_height="45dp"
		android:layout_gravity="center"
		android:paddingLeft="15dp"
		android:paddingRight="10dp"/>
    <TextView 
        android:id="@+id/drawer_list_text"
        android:layout_width="wrap_content"
        android:layout_height="45dp"
        android:layout_gravity="center_vertical"
        android:gravity="center_vertical"
	android:minHeight="?android:attr/listPreferredItemHeightSmall"
	android:paddingLeft="5dp"
	android:textAppearance="?android:attr/textAppearanceListItemSmall"
        android:textColor="#bb000000"
        />
    
</LinearLayout>


该布局显示的是图片在左,文字在右,android:minHeight="?android:attr/listPreferredItemHeightSmall"还有android:textAppearance="?android:attr/textAppearanceListItemSmall" 这些都是Android自带的属性,在IDE单击链接可以找到源码,具体不是很了解,"?"表示使用Theme中设定的值,Theme是一个style,在<declare-styleable name="Theme">中定义了,android: 前缀代表是android的属性。大概的意思是:使用Android中attr.xml中textAppearanceListItemSmall这个属性

接下来就可以编写java代码了。在MainActivity.java文件中


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;


public class MainActivity extends Activity implements OnItemClickListener{

	//ListView
	private ListView listView;

	//listview列表项对应的文字
	private String[] listView_Text;
	
	//listview的列表项,存放文字图片信息的
	private List<HashMap<String,Object>> listView_Items;

	//listview列表项对应的图片
	private int[] listView_Image;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO 自动生成的方法存根
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
	
		//listview所有的listItem的文字
		listView_Text = new String[]{"收集箱","待办事项","今日代办","明日代办","日程","等待","计划任务","项目","目标","情境","打卡"};
		//listview所有的listItem对应的图片,其中有某项为0,即对应的item项没有图片
		listView_Image = new int[]{R.drawable.collection_box,0,R.drawable.today,R.drawable.tomorrow,R.drawable.schedule,
				R.drawable.wait,0,R.drawable.project,R.drawable.target,R.drawable.schedule,
				R.drawable.punch_clock};
		
		//初始化listview组件
		initListView();
	}
	
	
	
	 //* 初始化listview,并设置监听事件
	 
	private void initListView() {
		// TODO 自动生成的方法存根
		//获取ListView控件
		listView = (ListView) findViewById(R.id.left_drawer);
		
		//为每一项ListView的item设置对应的图片和对应的文字
		listView_Items = new ArrayList<HashMap<String,Object>>();
		for(int i=0;i<listView_Text.length;i++){
			HashMap<String,Object> map = new HashMap<String,Object>();
			map.put("List_Image",listView_Image[i]);
			map.put("List_Text",listView_Text[i]);
			listView_Items.add(map);
		}
		
		//自定义适配器,传入listView_Items和当前上下文
		ListView_BaseAdapter List_Adapter = new ListView_BaseAapter(listView_Items,MainActivity.this);
		
		//为listView添加适配器
		listView.setAdapter(List_Adapter);
		
		//为listView添加监听事件
		listView.setOnItemClickListener(this);
	}
	
	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position,
			long id) {
		// TODO 自动生成的方法存根
	}

}


要实现自定义的ListView,就要自定义相应的适配器。ListView_BaseAdapter.java文件:


import java.util.HashMap;
import java.util.List;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

/*
 * 继承BaseAdapter类,实现自定义的适配器
 * 工作原理:listView在绘制时会首先调用getCount()方法得到绘制次数,然后通过getView方法一层一层进行绘制
 * 所以我们可以在getView()方法中根据position(当前绘制的ID)来修改绘制内容。
 * 而getItem()和getItemId()则在需要处理和取得数据时调用
 * areAllItemsEnabled()和isEnabled()方法一起使用,areAllItemsEnabled()表示是否所有项都可以点击
 * isEnabled()则表示当前项position是否可点击
 * 如果某一项不可以点击,则它的分割线不会显示
 */
public class ListView_BaseAdapter extends BaseAdapter {

	//listview的列表项,存放文字图片信息的
	private List<HashMap<String,Object>> listView_Items;
	
	//listview所在的上下文
	private Context mContext;
	
	//自定义构造函数,接受listView的item值和listView的上下文
	public ListView_BaseAdapter(List<HashMap<String, Object>> listView_Items,
			Context mContext) {
		this.listView_Items = listView_Items;
		this.mContext = mContext;
	}
	
	
	
	//获得绘制的次数
	@Override
	public int getCount() {
		// TODO 自动生成的方法存根
		return listView_Items.size();
	}


	//获得当前position项的Item
	@Override
	public HashMap<String,Object> getItem(int position) {
		// TODO 自动生成的方法存根
		return listView_Items.get(position);
	}

	//获得position即当前ID
	@Override
	public long getItemId(int position) {
		// TODO 自动生成的方法存根
		return position;
	}

	//是否所有项都是可以选择和可以点击的
	@Override
	public boolean areAllItemsEnabled() {
		// TODO 自动生成的方法存根
		return false;
	}
	
	//当前项是否是可点击和可选择的 
	@Override
	public boolean isEnabled(int position) {
		// TODO 自动生成的方法存根
		/*
		 * 当某些是不可以点击时,该项对应位置的分割线不会出现
		 */
		if( position == 1 || position == 6){
			return false;
		}else
			return true;
		
	}
	
	//绘制listView的Item的方法
	@Override
	public View getView(int position, View convertView, ViewGroup parent) {
		// TODO 自动生成的方法存根
		ImageView imageView;
		TextView textView;
		
		convertView = LayoutInflater.from(mContext).inflate(R.layout.list_item, null);
		imageView = (ImageView) convertView.findViewById(R.id.list_image);
		textView = (TextView) convertView.findViewById(R.id.list_text);

		/*
		 * 第1,6项不设置图标,所以只需设置textView即可,
		 * 同时注意在List<HashMap<String,Object>> listView_Items中
		 * 图片数组在1,6位置对应的int要设置为0
		 */

		if(position == 1 || position == 6 ){
			textView.setText((String)getItem(position).get("List_Text"));
			textView.setTextSize(15);
			textView.setTextColor(0xffaaaaaa);
			/*
			 * 设置imageView的宽高参数,因为该位置就算没有图片,但是在xml定义的时候还是会占空间,
			 * 所以要把该位置的imageView宽高设为0
			 */
			LayoutParams para = imageView.getLayoutParams();
			para.height = 0;
			para.width = 15;
			imageView.setLayoutParams(para);
			
		}else{
			imageView.setImageResource((int)getItem(position).get("List_Image"));
			textView.setText((String)getItem(position).get("List_Text"));
		}
		
		return convertView;
	}
}


这样就可以使用自定义效果的listview了。

在自定义的adapter适配器中,原本可以在getView方法中定义ViewHolder,以重用被回收的listview的item项,达到节省资源的目的,但是这样有个问题,就是之前为某一特殊项item定义的属性,比如颜色,也会被重用,这样会导致其他不需要该属性的item也得到了这个属性,所以这里不用ViewHolder。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值