在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。