ExpandableListView 分组列表视图
和ListView不同的是它是一个两级的滚动列表视图,每一个组可以展开,显示一些子项,类似于QQ列表,这些项目来至于ExpandableListAdapter的子类,也就是说,要实现向里面添加项目,必
须写一个子类实现ExpandableListAdapter的接口或者使用系统为我们实现在子类
常用属性:
1. android:childDivider 指定各组内子类表项之间的分隔条,
2. android:childIndicator 显示在子列表旁边的Drawable对象
3. android:childIndicatorLeft 子列表项指示符的左边约束位置
4. android:childIndicatorRight 子列表项指示符的右边约束位置
5. android:groupIndicator 显示在组列表旁边的Drawable对象
6. android:indicatorLeft 组列表项指示器的左边约束位置
7. android:indicatorRight 组列表项指示器的右边约束位置
一般适用于ExpandableListView的Adapter都要继承BaseExpandableListAdapter这个类,并且必须重载getGroupView和getChildView这两个最为重要的方法。
当扩展BaseExpandableListAdapter时,关键是实现如下四个方法:
抽象方法
1. //取得显示给定分组给定子位置的数据用的视图。
2. public abstract View getChildView (int groupPosition, intchildPosition
, boolean isLastChild, ViewconvertView, ViewGroup parent){
3. //groupPosition 包含要取得子视图的分组位置。
4. //childPosition 分组中子视图(要返回的视图)的位置。
5. //isLastChild 该视图是否为组中的最后一个视图。
6. //convertView 如果可能,重用旧的视图对象,使用前你应该保证视图对象为非
空,并且是否是合适的类型,如果该对象不能转换为可以正确显示数据的视图,该方法就创建新
视图.不保证使用先前由getChildView(int, int,boolean, View, ViewGroup)创建的
视图.
7. //parent 该视图最终从属的父视图.
8. 返回 指定位置相应的子视图.
9. }
10.
11. //取得指定分组的子元素数。
12. public abstract int getChildrenCount (int groupPosition){
13. //groupPosition 要取得子元素个数的分组位置。
14. 返回 指定分组的子元素个数.
15. }
16.
17. //取得用于显示给定分组的视图.这个方法仅返回分组的视图对象,要想获取子元素的视图对象
,就需要调用getChildView(int, int, boolean, View, ViewGroup)。
18. public abstract View getGroupView (int groupPosition,
booleanisExpanded, View convertView, ViewGroupparent){
19. //groupPosition 决定返回哪个视图的组位置.
20. //isExpanded 该组是展开状态还是收起状态 .
21. //convertView 如果可能,重用旧的视图对象.使用前你应该保证视图对象为非空,
并且是否是合适的类型.如果该对象不能转换为可以正确显示数据的视图,该方法就创建新视图.
不保证使用先前由getGroupView(int, boolean,View, ViewGroup)创建的视图.
22. //parent 该视图最终从属的父视图.
23. 返回 指定位置相应的组视图.
24. }
25.
26. //取得分组数。
27. public abstract int getGroupCount (){
28. 返回 分组数。
29. }
注意:在XML布局文件中,如果ExpandableListView上一级视图的大小没有严格定义的话,则不能对ExpandableListView的android:layout_height属性使用wrap_content值。(例如,如果上一级视图是ScrollView的话,则不应该指定wrap_content的值,因为它可以是任意的长度。不过,如果ExpandableListView的上一级视图有特定的大小的话,比如100像素,则可以使用wrap_content)
示例图如下:
//Activity类
public class MainActivity extends Activity {
List<Group> mlist=new ArrayList<Group>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
intiData();
ExpandableListView el=(ExpandableListView) findViewById(R.id.el);
FriendAdapter adapter = new FriendAdapter(this, mlist);
el.setAdapter(adapter);
}
private void intiData() {
// 创建一些数据来测试
Group group1 = new Group();
User user1 = new User(R.drawable.p01, "蝴蝶", true, "假如此刻还有许些的难过,也许是美丽夜色伤感了我");
User user2 = new User(R.drawable.p02, "牡丹", true, "天长和地久若只是个传说,何必去追问谁对谁错");
User user3 = new User(R.drawable.p03, "杜鹃", false, "曾以为得到的就是快乐,筋疲力尽还要彼此折磨");
User user4 = new User(R.drawable.p04, "兰花", true, "海誓和山盟变成了泡沫,难道只有放弃才能解脱");
group1.addUser(user1);
group1.addUser(user2);
group1.addUser(user3);
group1.addUser(user4);
group1.name = "小学同学";
Group group2 = new Group();
User user5 = new User(R.drawable.p05jpg, "芍药", false, "为什么付出那么多,你还是让我感到悲伤难过");
User user7 = new User(R.drawable.p07, "柔儿", true, "为什么付出那么多,竟然却越来越感到了迷惑");
group2.addUser(user5);
group2.addUser(user7);
group2.name = "陌生人";
Group group3 = new Group();
User user6 = new User(R.drawable.p06, "美女", true, "是我自己太过的软弱,还是上辈子欠你的太多");
group3.addUser(user6);
group3.name = "爱人";
mlist.add(group1);
mlist.add(group2);
mlist.add(group3);
}
}
//自己写的Adapter类
public class FriendAdapter extends BaseExpandableListAdapter {
private Context context;
private List<Group> mlist;
public FriendAdapter(Context context, List<Group> list) {
this.context = context;
this.mlist = list;
}
@Override
public int getGroupCount() {
return mlist.size();
}
@Override
public int getChildrenCount(int groupPosition) {
return mlist.get(groupPosition).size();
}
@Override
public Group getGroup(int groupPosition) {
return mlist.get(groupPosition);
}
@Override
public User getChild(int groupPosition, int childPosition) {
return mlist.get(groupPosition).list.get(childPosition);
}
@Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
@Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
@Override
public boolean hasStableIds() {
return true;
}
@Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
GroupHolder holder;
if (convertView == null) {
convertView = View.inflate(context, R.layout.group_activity, null);
holder = new GroupHolder(convertView);
convertView.setTag(holder);
}
holder = (GroupHolder) convertView.getTag();
Group group = getGroup(groupPosition);
holder.name.setText(group.name);
holder.online.setText(group.getCount() + "/" + group.size());
return convertView;
}
@Override
public View getChildView(int groupPosition, int childPosition,
boolean isLastChild, View convertView, ViewGroup parent) {
ChildHolder holder;
if (convertView == null) {
convertView = View.inflate(context, R.layout.user_activity, null);
holder = new ChildHolder(convertView);
convertView.setTag(holder);
}
holder = (ChildHolder) convertView.getTag();
User user = mlist.get(groupPosition).list.get(childPosition);
holder.img.setImageResource(user.getImgid());
holder.name.setText(user.getName());
holder.online.setText(user.isOnline ? "[在线]" : "[离线]");
holder.sign.setText(user.getSign());
return convertView;
}
@Override
public boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
}
class GroupHolder {
TextView name, online;
public GroupHolder(View convertView) {
name = (TextView) convertView.findViewById(R.id.group_name);
online = (TextView) convertView.findViewById(R.id.group_online);
}
}
class ChildHolder {
ImageView img;
TextView name, online, sign;
public ChildHolder(View convertView) {
name = (TextView) convertView.findViewById(R.id.user_name);
online = (TextView) convertView.findViewById(R.id.user_online);
sign = (TextView) convertView.findViewById(R.id.user_sign);
img = (ImageView) convertView.findViewById(R.id.user_img);
}
}
}
//第一个布局类 也就是分组类
public class Group {
List<User> list = new ArrayList<User>();
String name;
public int size() {
return list.size();
}
public void addUser(User user) {
list.add(user);
}
public int getCount() {
int sum=0;
for (User user : list) {
if (user.isOnline) {
sum++;
}
}
return sum;
}
}
//第二个布局类 也就是一个分组类中存在的元素类
ublic class User {
int imgid;
String name;
boolean isOnline;
String sign;
public User() {
super();
}
public User(int imgid, String name, boolean isOnline, String sign) {
super();
this.imgid = imgid;
this.name = name;
this.isOnline = isOnline;
this.sign = sign;
}
@Override
public String toString() {
return "User [imgid=" + imgid + ", name=" + name + ", isOnline="
+ isOnline + ", sign=" + sign + "]";
}
public int getImgid() {
return imgid;
}
public void setImgid(int imgid) {
this.imgid = imgid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public boolean isOnline() {
return isOnline;
}
public void setOnline(boolean isOnline) {
this.isOnline = isOnline;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
}
//把图像变成圆形的类
public class CircleImageView extends ImageView {
private static final Xfermode MASK_XFERMODE;
private Bitmap mask;
private Paint paint;
private int mBorderWidth = 10;
private int mBorderColor = Color.parseColor("#f2f2f2");
private boolean useDefaultStyle = false;
static {
PorterDuff.Mode localMode = PorterDuff.Mode.DST_IN;
MASK_XFERMODE = new PorterDuffXfermode(localMode);
}
public CircleImageView(Context context) {
super(context);
}
public CircleImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CircleImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CircularImage);
mBorderColor = a.getColor(R.styleable.CircularImage_border_color, mBorderColor);
final int def = (int) (2*context.getResources().getDisplayMetrics().density + 0.5f);
mBorderWidth = a.getDimensionPixelOffset(R.styleable.CircularImage_border_width, def);
a.recycle();
}
private void useDefaultStyle(boolean useDefaultStyle) {
this.useDefaultStyle = useDefaultStyle;
}
@Override
protected void onDraw(Canvas canvas) {
if(useDefaultStyle) {
super.onDraw(canvas);
return ;
}
final Drawable localDraw = getDrawable();
if(localDraw == null) {
return ;
}
if(localDraw instanceof NinePatchDrawable) {
return ;
}
if (this.paint == null) {
final Paint localPaint = new Paint();
localPaint.setFilterBitmap(false);
localPaint.setAntiAlias(true);
localPaint.setXfermode(MASK_XFERMODE);
this.paint = localPaint;
}
final int width = getWidth();
final int height = getHeight();
int layer = canvas.saveLayer(0.0F, 0.0F, width, height, null, 31);
localDraw.setBounds(0, 0, width, height);
localDraw.draw(canvas);
if ((this.mask == null) || (this.mask.isRecycled())) {
this.mask = createOvalBitmap(width, height);
}
canvas.drawBitmap(this.mask, 0.0F, 0.0F, this.paint);
canvas.restoreToCount(layer);
drawBorder(canvas, width, height);
}
private void drawBorder(Canvas canvas, final int width, final int height) {
if(mBorderWidth == 0) {
return ;
}
final Paint mBorderPaint = new Paint();
mBorderPaint.setStyle(Paint.Style.STROKE);
mBorderPaint.setAntiAlias(true);
mBorderPaint.setColor(mBorderColor);
mBorderPaint.setStrokeWidth(mBorderWidth);
canvas.drawCircle(width/2, height/2, (width-mBorderWidth)/2, mBorderPaint);
canvas = null;
}
public Bitmap createOvalBitmap(final int width, final int height) {
Bitmap.Config localConfig = Bitmap.Config.ARGB_8888;
Bitmap localBitmap = Bitmap.createBitmap(width, height, localConfig);
Canvas localCanvas = new Canvas(localBitmap);
Paint localPaint = new Paint();
final int padding = (mBorderWidth - 3) > 0 ? mBorderWidth - 3 : 1;
RectF localRectF = new RectF(padding, padding, width - padding, height - padding);
localCanvas.drawOval(localRectF, localPaint);
return localBitmap;
}
}
//需要在values中建立一个为circle_attr.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CircularImage">
<attr name="border_width" format="dimension" />
<attr name="border_color" format="color" />
</declare-styleable>
</resources>
//主布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.xykj.id05_10_12work7_4.MainActivity" >
<ExpandableListView
android:id="@+id/el"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
></ExpandableListView>
</RelativeLayout>
//第一个布局也就是分组的那个布局
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="20dp" >
<TextView
android:id="@+id/group_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="组名"/>
<TextView
android:id="@+id/group_online"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1/3"
/>
</RelativeLayout>
//第二个布局也就是分组里面显示的布局
<?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" >
<com.xykj.id05_10_12work7_4.CircleImageView
android:layout_width="80dp"
android:layout_height="80dp"
android:id="@+id/user_img"
android:src="@drawable/ic_launcher"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:id="@+id/user_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="名称"
android:textSize="18sp"
/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:id="@+id/user_online"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="[在线]"
android:textStyle="bold" />
<TextView
android:id="@+id/user_sign"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="签名" />
</LinearLayout>
</LinearLayout>
</LinearLayout>
ImageSwitcher图像切换器
图像切换器使用ImageSwitcher表示,用于实现类似于windows操作系统下的”Windows照片
查询器”中的上一张,下一张切换图片的功能,在使用ImageSwitcher时,必须实现ViewSwitcher.ViewFactory接口,并通过makeView()方法来创建用于显示图片的ImageView
makeView()方法将返回一个显示图片的ImageView.在使用图像切换器时,还有一个方法非常
重要,那就是setImageResource()方法,该方法用于指定要在ImageSwitcher中显示的图片资源.
视图如下图:
package com.example.lesson7_imageswitcher;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageSwitcher;
import android.widget.ImageView;
import android.widget.ViewSwitcher.ViewFactory;
public class MainActivity extends Activity {
int[] resId = { R.drawable.img01, R.drawable.img02, R.drawable.img03,
R.drawable.img04, R.drawable.img05, R.drawable.img06 };
int index = 0;
ImageSwitcher is;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
is = (ImageSwitcher) findViewById(R.id.is);
is.setFactory(new ViewFactory() {
// 用什么View来展示
@Override
public View makeView() {
ImageView iv = new ImageView(getBaseContext());
return iv;
}
});
is.setImageResource(resId[index]);
}
public void up(View v) {
index--;
if (index < 0)
index = resId.length - 1;
is.setImageResource(resId[index]);
}
public void down(View v) {
index++;
if (index == resId.length)
index = 0;
is.setImageResource(resId[index]);
}
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
tools:context="com.example.lesson7_imageswitcher.MainActivity" >
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="up"
android:text="上一张" />
<ImageSwitcher
android:id="@+id/is"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</ImageSwitcher>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="down"
android:text="下一张" />
</LinearLayout>
Gallery画廊视图(已过期,还能用)
画廊视图使用Gallery表示,能够按水平方向显示内容,并且可以手指直接拖动图片和移动,一般用
来浏览图片,,被选中的选项位于中间,并且可以响应事件显示信息.在使用画廊视图时,首先在屏幕
上添加Gallery组件,通常使用标记在XML而布局文件中添加.
画廊视图在4.0后已经过期,但是我们仍然可以使用,不过后面我们将用水平的ListView
自定义组件来实现这个效果,在自定义视图中讲解。
常用属性:
1. android:animationDuration 用于设置列表项切换时的动画持续时间
2. android:gravity 用于设置对齐方式
3. android:spacing 用于设置列表项之间的间距
4. android:unselectedAlpha 用于设置没有选中的列表项的透明度
示例图如下:
public class MainActivity extends Activity {
//RecyleView
Gallery gl;
int[] resId = { R.drawable.img01, R.drawable.img02, R.drawable.img03,
R.drawable.img04, R.drawable.img05, R.drawable.img06 };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
gl = (Gallery) findViewById(R.id.gl);
gl.setAdapter(adapter);
gl.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
Log.e("TAG", "--" + position + "被选中");
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// TODO Auto-generated method stub
}
});
}
private BaseAdapter adapter = new BaseAdapter() {
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null)
convertView = new ImageView(MainActivity.this);
ImageView iv = (ImageView) convertView;
iv.setPadding(20, 20, 20, 20);
iv.setImageResource(resId[position]);
return convertView;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public Object getItem(int position) {
return null;
}
@Override
public int getCount() {
return resId.length;
}
};
}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.lesson7_gallery.MainActivity" >
<Gallery
android:id="@+id/gl"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</RelativeLayout>