分组列表视图(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. javascript innerHTML、outerHTML、innerText、outerText的区别

    1.功能讲解: innerHTML 设置或获取位于对象起始和结束标签内的 HTML outerHTML 设置或获取对象及其内容的 HTML 形式 innerText 设置或获取位于对象起始和结束标签内 ...

  2. 关于android应用闪屏的几种情况

    1.主菜单进入某应用闪屏: 常见是一个空的activity作为launcher属性,实际上它什么事业没干,真正干事情的是从它通过intent启动的activity. 例子: public class ...

  3. N3292x IBR介绍

    N3292x IBR介绍 1 IBR启动流程 图1-1 IBR启动流程 CHIP_CFG[0] Mode 0 Boot from IBR Recovery Mode with crystal inpu ...

  4. 02_ Windows与Linux双重引导

    1. Grub2引导window. ---------------------步骤1--------------------------------- vim /etc/grub.d/40_custo ...

  5. android异常之emulator-arm.exe已停止工作

    我遇到的这个问题通过降低了AVD的分辨率后解决了,估计是电脑的显卡不行.

  6. 【转】关于TP3.2 验证码不显示的问题

    在调用验证码之前加上 ob_clean(); 不显示验证码的代码: public function verify(){                $verify = new \Think\Veri ...

  7. jquery 事件绑定(1)

    $(function(){ $("#panel h5.head").bind("click",function(){ $(this).next().show() ...

  8. uva 580 危险的组合(排列组合)

    Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Descript ...

  9. sql server 调优----索引未使用

    SELECT TOP 1000o.name AS 表名, i.name AS 索引名, i.index_id AS 索引id, dm_ius.user_seeks AS 搜索次数, dm_ius.us ...

  10. asp.net webform 局部发布更新

    一:关于webform编译 编译时会将每个aspx文件单独生成dll文件于bin目录下.也会将引用的dll存放于bin目录 二:对界面或者引用的dll(如BLL层,DAL层等)做了修改更新后在服务器只 ...