在Android应用程序开发中,我们经常用到ListView这个控件,可能大家会对方方正正的ListView控件感到厌烦,这里来实现圆角的ListView,并放在ScrollView控件中。实现类如下图这种效果,如图
这里我们沿用Android系统的MVC软件设计模式。首先,在res/drawable文件夹下新建一个listview_round_corner_bg.xml文件,作为ListView的背景,代码如下:
<?xml version="1.0" encoding="UTF-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <!--圆角 --> <corners android:radius="8dp" /> <!-- 背景填充 --> <solid android:color="@color/white" /> <!-- 描边 --> <stroke android:width="1dp" android:color="@color/gray" /> </shape> 我们点击ListView的Item时,需要设计四种情况:
1.只有一项,那么上下左右四个角都要是圆角,新建一个listview_round_corner_selector.xml
<?xml version="1.0" encoding="UTF-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- 按下时背景图片 --> <item android:state_pressed="true" android:drawable="@drawable/listview_round_corner_shape_pressed" /> <!-- 默认是背景图片 --> <item android:drawable="@drawable/listview_round_corner_shape_normal" /> </selector> 其中用到的listview_round_corner_shape_pressed.xml:
<?xml version="1.0" encoding="UTF-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <!--圆角 --> <corners android:radius="8dp" /> <!-- 背景填充 --> <solid android:color="@color/gray" /> <!-- 描边 --> <stroke android:width="1dp" android:color="@color/gray" /> </shape> 另一个listview_round_corner_shape_normal.xml: <?xml version="1.0" encoding="UTF-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" > <!--圆角 --> <corners android:radius="8dp" /> <!-- 背景填充 --> <solid android:color="@color/white" /> <!-- 描边 --> <stroke android:width="1dp" android:color="@color/gray" /> </shape> 2.不止一项的时候,当点击第一项时候,应该是左上角和右上角圆角
3.不止一项的时候,当点击中间某一项时候,应该是没有圆角
4.不止一项的时候,当点击最后一项时候,应该是左下角和右下角圆角
后面三种情况代码就不在这里贴出来了,详见附加文件
好了,到这里我们再继承一下Listview控件,创建一个自己的ListView控件,override一下onInterceptTouchEvent这个函数
public class RoundCornerListView extends ListView{ public RoundCornerListView(Context context) { super(context); // TODO Auto-generated constructor stub } /** * @param context * @param attrs * @param defStyle */ public RoundCornerListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // TODO Auto-generated constructor stub } /** * @param context * @param attrs */ public RoundCornerListView(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } /**** * 拦截触摸事件 */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { // TODO Auto-generated method stub switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: int x = (int) ev.getX(); int y = (int) ev.getY(); int itemnum = pointToPosition(x, y); if (itemnum == AdapterView.INVALID_POSITION) break; else{ if(itemnum==0){ if(itemnum==(getAdapter().getCount()-1)){ setSelector(R.drawable.listview_round_corner_selector);//上面的第一种情况 }else{ setSelector(R.drawable.listview_round_corner_top_selector);//第二种情况 } }else if(itemnum==(getAdapter().getCount()-1)) setSelector(R.drawable.listview_round_corner_bottom_selector);//第四种情况 else{ setSelector(R.drawable.listview_round_corner_medium_selector);//第三种情况 } } break; case MotionEvent.ACTION_UP: break; } return super.onInterceptTouchEvent(ev); } } 然后用这个RoundCornerListView控件创建属于自己的ListView,到此为止我们已经解决了ListView的圆角显示问题,现在来解决在ScrollView中显示ListView的问题,我们都知道这两个控件是“死敌”,解决的办法就是动态设置ListView的大小:
/*** * 动态设置listview的高度 * * @param listView */ public void setListViewHeightBasedOnChildren(ListView listView) { ListAdapter listAdapter = listView.getAdapter(); if (listAdapter == null) { return; } int totalHeight = 0; for (int i = 0; i < listAdapter.getCount(); i++) { View listItem = listAdapter.getView(i, null, listView); listItem.measure(0, 0); totalHeight += listItem.getMeasuredHeight(); } ViewGroup.LayoutParams params = listView.getLayoutParams(); params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1)); // params.height += 5;// if without this statement,the listview will be // a // little short // listView.getDividerHeight()获取子项间分隔符占用的高度 // params.height最后得到整个ListView完整显示需要的高度 listView.setLayoutParams(params); } 在ListView设置setAdapter以后调用这个函数就ok了。
注意,在这里有个问题就是假如我们调用的ListView中Item是系统自带的话,例如:android.R.layout.simple_expandable_list_item_1这个Item,调用上面的函数时候会显示不正确,应该是检测Height时候不正确,所以这里我们自己写了一个listview_item.xml:
<?xml version="1.0" encoding="utf-8"?> <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/text1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLarge" android:gravity="center_vertical" android:textColor="#000000" android:paddingLeft="30dip" android:minHeight="?android:attr/listPreferredItemHeight" />