分组列表视图(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、首相activity_main.xml布局搭建

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"> <ExpandableListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/elv"/> </RelativeLayout>

activity_main.xml

2、然后是搭建QQ分组的布局

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" > <TextView
android:id="@+id/groupName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:text="分组名称" /> <TextView
android:id="@+id/groupOnline"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0/8" /> </RelativeLayout>

item_group.xml

3、再搭建分组中各选项的布局(QQ联系人,包括头像,昵称,签名)

   这里由于引用了外部的自定义的控件,所以这里包名加类名

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:orientation="horizontal" > <com.test.lesson7_expandablelistview.CircleImageView
android:id="@+id/img"
android:layout_width="80dp"
android:layout_height="80dp"
android:src="@drawable/ic_launcher" /> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:orientation="vertical" > <TextView
android:id="@+id/nickName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="昵称"
android:textSize="18sp" /> <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:orientation="horizontal" > <TextView
android:id="@+id/online"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="[在线]" /> <TextView
android:id="@+id/sign"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="我要飞的更高~" />
</LinearLayout>
</LinearLayout> </LinearLayout>

item_child.xml

4、圆角图片形状

  在res/values中建circle_attr.xml

 <resources>

     <declare-styleable name="CircularImage">
<attr name="border_width" format="dimension" />
<attr name="border_color" format="color" />
</declare-styleable> </resources>

5、然后新建一个CircleImageView继承ImageView

  此处自定义控件是在GitHub上下载

 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;
} }

CircleImageView

6、创建Group类

 public class Group {
//分组名
public String groupName;
//有很多User
public List<User> list; public Group(String groupName){
this.groupName = groupName;
list = new ArrayList<User>();
}
//添加User
public void addUser(User user){
list.add(user);
} //获取某个分组中User的数量
public int getChildCount() {
return list.size();
}
//获取某个分组中User在线的数量
public int getOnlineCount(){
int sum = 0;
for (User user : list) {
if(user.isOnline()){
sum++;
}
}
return sum;
}
//获取分组中某个孩子
public User getChild(int childPosition) {
return list.get(childPosition);
} }

Group.java

7、创建User类

 public class User {
private int imgId;
private String nickName;
private boolean isOnline;
private String sign; public User() {
super();
}
public User(int imgId, String nickName, boolean isOnline, String sign) {
super();
this.imgId = imgId;
this.nickName = nickName;
this.isOnline = isOnline;
this.sign = sign;
} public int getImgId() {
return imgId;
}
public void setImgId(int imgId) {
this.imgId = imgId;
}
public String getNickName() {
return nickName;
}
public void setNickName(String nickName) {
this.nickName = nickName;
}
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;
} }

User

8、设置适配器

 public class GroupAdapter extends BaseExpandableListAdapter{

     Context context;
List<Group> list; public GroupAdapter(Context context, List<Group> list) {
this.context = context;
this.list = list;
} @Override
public View getGroupView(int groupPosition, boolean isExpanded,
View convertView, ViewGroup parent) {
GroupHolder holder;
if(convertView == null){
convertView = View.inflate(context, R.layout.item_grouplayout, null);
holder = new GroupHolder(convertView);
convertView.setTag(holder);
}else{
holder = (GroupHolder) convertView.getTag();
}
//设置数据
Group group = getGroup(groupPosition);
holder.groupName.setText(group.groupName);
holder.groupOnline.setText(group.getOnlineCount()+"/"+getChildrenCount(groupPosition)); 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.item_childlayout, null);
holder = new ChildHolder(convertView);
convertView.setTag(holder);
}else{
holder = (ChildHolder) convertView.getTag();
}
//设置数据
User user = getGroup(groupPosition).getChild(childPosition);
holder.img.setImageResource(user.getImgId());
holder.nickName.setText(user.getNickName());
holder.online.setText(user.isOnline()?"[在线]":"[离线]");
holder.sign.setText(user.getSign()); return convertView; } class GroupHolder{
TextView groupName;
TextView groupOnline; public GroupHolder(View convertView){
groupName = (TextView) convertView.findViewById(R.id.groupName);
groupOnline = (TextView) convertView.findViewById(R.id.groupOnline); }
}
class ChildHolder{
ImageView img;
TextView nickName;
TextView online;
TextView sign; public ChildHolder(View convertView){
img = (ImageView) convertView.findViewById(R.id.img);
nickName = (TextView) convertView.findViewById(R.id.nickName);
online = (TextView) convertView.findViewById(R.id.online);
sign = (TextView) convertView.findViewById(R.id.sign); } } @Override
public int getGroupCount() {
return list.size();
} @Override
public int getChildrenCount(int groupPosition) {
return list.get(groupPosition).getChildCount();
} @Override
public Group getGroup(int groupPosition) {
return list.get(groupPosition);
} @Override
public User getChild(int groupPosition, int childPosition) {
return list.get(groupPosition).getChild(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 boolean isChildSelectable(int groupPosition, int childPosition) {
return true;
} }

GroupAdapter

9、MainActivity.java中将所有组件找到,初始化数据源,并给ListView设置适配器

 public class MainActivity extends Activity {

     ExpandableListView elv;
private List<Group> list = new ArrayList<Group>();
int[] img = new int[6]; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
elv = (ExpandableListView) findViewById(R.id.elv);
GroupAdapter adapter = new GroupAdapter(getBaseContext(), list);
elv.setAdapter(adapter); } private void initData() {
for (int i = 0; i < img.length; i++) {
try {
img[i] = R.drawable.class.getField("img0"+(i+1)).getInt(null);
} catch (Exception e) {
e.printStackTrace();
}
} Group group1 = new Group("贵圈好乱");
group1.addUser(new User(img[0], "张翰", true, "我爱娜扎!"));
group1.addUser(new User(img[1], "郑爽", false, "妈蛋,要么瘦,要么死!"));
group1.addUser(new User(img[2], "胡彦斌", true, "其实我只是长得抽象了"));
group1.addUser(new User(img[5], "撒贝宁", true, "子怡当年没选择我是个美丽的错误"));
group1.addUser(new User(img[3], "杨幂", false, "其实我跟恺威已经离婚了,现在跟李易峰在一起,就酱~")); Group group2 = new Group("超星星");
group2.addUser(new User(img[4], "林志炫", true, "其实我的小肚子都是唱歌导致的,哈哈哈")); list.add(group1);
list.add(group2); } }

MainActivity.java

运行效果有点渣渣。请忽略:

Android ExpandableListView BaseExpandableListAdapter (类似QQ分组列表)的更多相关文章

  1. android开发之ExpandableListView的使用,实现类似QQ好友列表

    由于工作需要,今天简单研究了一下ExpandableListView,做了一个类似QQ列表的Demo,和大家分享一下. 效果图如下: 先来看看主布局文件: <RelativeLayout xml ...

  2. android 网络广播 类似QQ动态检查网络

    private ConnectivityManager mConnectivityManager; private NetworkInfo netInfo; 在onCreate 注册广播 Intent ...

  3. iOS 实现类似QQ分组样式的几种方式

    思路 思路很简单,对模型数据操作或则控制界面显示 先看下json部分数据 "chapterDtoList": [{ "token": null, "i ...

  4. CSS+Jquery实现QQ分组列表

    实现效果图如下: 说明: 1.css隐藏分组下的好友内容: 2.Jquery实现点击分组项事件,实现好友内容的显示和隐藏: 3.样式1,可展开多个分组:样式2,只能有一个分组展开: 源码: <! ...

  5. iOS UITableView制作类似QQ好友列表视图

                #import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplicationDele ...

  6. ExpandableListView仿QQ好友列表

    本例中,对ExpandableListView中的数据进行了封装,分为两个JavaBean,一个为Group类表示组信息,一个Child类表示该组下子列表信息: Group: public class ...

  7. [iOS基础控件 - 6.9.3] QQ好友列表Demo TableView

    A.需求 1.使用plist数据,展示类似QQ好友列表的分组.组内成员显示缩进功能 2.组名使用Header,展示箭头图标.组名.组内人数和上线人数 3.点击组名,伸展.缩回好友组   code so ...

  8. swift 实现QQ好友列表功能

    最近项目中有类似QQ好友列表功能,整理了一下,话不多说,直接上代码 import UIKit class QQFriend: NSObject { var name: String? var intr ...

  9. Android UI视图效果篇之仿QQ好友列表分组悬浮PinnedHeaderExpandableListView

    楼主是在平板上測试的.图片略微有点大,大家看看效果就好 接下来贴源代码: PinnedHeaderExpandableListView.java 要注意的是 在 onGroupClick方法中pare ...

随机推荐

  1. .Net程序员 Solr-5.3之旅 (一)Solr入门

    阅读目录 引言 Lunece是什么? Solr是什么 JAVA环境搭建 JAVA环境搭建之变量配置 Tomcat简单配置 结尾 引言 君子生非异也,善假于物也. Java和.Net哪个好,我们也不需要 ...

  2. Razor视图引擎基础语法

    在VS2010中新建一个MVC3项目可以看出与以往的MVC2发生了很明显的变化 1.ASP.NET MVC3必要的运行环境为.NET 4.0 (想在3.5用MVC3,没门!) 2.默认MVC3模板项目 ...

  3. Mavne + Spring整合CXF

    http://blog.csdn.net/xiongyu777888/article/details/23787615(没毛病) http://blog.csdn.net/hbsong75/artic ...

  4. Swift - 02 - 常量和变量

    //: Playground - noun: a place where people can play import UIKit var str = "Hello, playground& ...

  5. SVN 不能提交, 看不到日志, 出现乱码. 解决方案.

    需要工具 sprite3: 点这里下载. 解决问题 如本文标题所写. 我遇到过几次一样的问题, 每次都很蛋疼的把目录重新检出, 浪费时间, 又伤了脾气. 下面是我在百度经验找到的一片帖子, 效果杠杠的 ...

  6. 【USACO 3.1.3】丑数

    [描述] 对于一给定的素数集合 S = {p1, p2, ..., pK}, 来考虑那些质因数全部属于S 的数的集合.这个集合包括,p1, p1p2, p1p1, 和 p1p2p3 (还有其它).这是 ...

  7. TalkingData游戏版本在Cocos2d-x 3.2使用

    最近一直忙别的方面的事情,没有太关注cocos2dx的发展情况,竟然已经更新到了3.2的版本,总的来说3.2比较3.0在使用上会有一些路径的变成,包括ios的引用路径和android上的build的p ...

  8. id class

    id 选择器可以为标有特定 id 的 HTML 元素指定特定的样式. HTML元素以id属性来设置id选择器,CSS 中 id 选择器以 "#" 来定义. 以下的样式规则应用于元素 ...

  9. win7 该任务映像已损坏或一篡改

    首先找到任务计划程序快捷方式的位置,我的是win7系统,是在:控制面板-->管理工具-->任务计划程序 打开任务计划程序出现了下面的异常提示: 出现了这个异常之后,创建任务.创建基本任务菜 ...

  10. $().change事件

    change([[data],fn]) 当元素的value值发生改变时发生change事件 适用于: 文本域 text textarea和select元素 text textarea 元素失去焦点时发 ...