Android ExpandableListView BaseExpandableListAdapter (类似QQ分组列表)
分组列表视图(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分组列表)的更多相关文章
- android开发之ExpandableListView的使用,实现类似QQ好友列表
由于工作需要,今天简单研究了一下ExpandableListView,做了一个类似QQ列表的Demo,和大家分享一下. 效果图如下: 先来看看主布局文件: <RelativeLayout xml ...
- android 网络广播 类似QQ动态检查网络
private ConnectivityManager mConnectivityManager; private NetworkInfo netInfo; 在onCreate 注册广播 Intent ...
- iOS 实现类似QQ分组样式的几种方式
思路 思路很简单,对模型数据操作或则控制界面显示 先看下json部分数据 "chapterDtoList": [{ "token": null, "i ...
- CSS+Jquery实现QQ分组列表
实现效果图如下: 说明: 1.css隐藏分组下的好友内容: 2.Jquery实现点击分组项事件,实现好友内容的显示和隐藏: 3.样式1,可展开多个分组:样式2,只能有一个分组展开: 源码: <! ...
- iOS UITableView制作类似QQ好友列表视图
#import <UIKit/UIKit.h> @interface AppDelegate : UIResponder <UIApplicationDele ...
- ExpandableListView仿QQ好友列表
本例中,对ExpandableListView中的数据进行了封装,分为两个JavaBean,一个为Group类表示组信息,一个Child类表示该组下子列表信息: Group: public class ...
- [iOS基础控件 - 6.9.3] QQ好友列表Demo TableView
A.需求 1.使用plist数据,展示类似QQ好友列表的分组.组内成员显示缩进功能 2.组名使用Header,展示箭头图标.组名.组内人数和上线人数 3.点击组名,伸展.缩回好友组 code so ...
- swift 实现QQ好友列表功能
最近项目中有类似QQ好友列表功能,整理了一下,话不多说,直接上代码 import UIKit class QQFriend: NSObject { var name: String? var intr ...
- Android UI视图效果篇之仿QQ好友列表分组悬浮PinnedHeaderExpandableListView
楼主是在平板上測试的.图片略微有点大,大家看看效果就好 接下来贴源代码: PinnedHeaderExpandableListView.java 要注意的是 在 onGroupClick方法中pare ...
随机推荐
- ASP.NET常用编程代码(一)
1.为按钮添加确认对话框 Button1.Attributes.Add("onclick","return confirm(’确认?’)");button.at ...
- Directory类
string[] pathes = Directory.GetDirectories(@"G:\ReawFiles");//获得所有的文件夹 string[] pathes = D ...
- JavaScript 之 关键内容
词法作用域.调用对象.作用域链.闭包.构造函数.原型.类.继承 局部变量查找路径 属性查找路径
- html5 的百度地图连接
在一些网站上,我们经常会看到一些地址会有一个图标的形式展现,当你点击的时候就会加载一个你点击区域的地图出来,很神奇的一个功能,在之前是没有这样功能的,都是直接写上地址,你要去的话自己找去吧,现在有了这 ...
- 使用Jquery解析Json
利用原生JSON对象,将对象转为字符串 [javascript] view plaincopy var jsObj = {}; jsObj.testArray = [1,2,3,4,5]; j ...
- 由于权限不足而无法读取配置文件出现的HTTP 500.19解决办法
无法访问请求的页面,因为该页的相关配置数据无效. 如下图: 解决方法, 到站点目录的属性,安全标签,添加用户(Everyone),并给修改权限:
- 写给新手看的Flask+uwsgi+Nginx+Ubuntu部署教程
学习 Flask,写完一个 Flask 应用需要部署的时候,就想着折腾自己的服务器.根据搜索的教程照做,对于原理一知半解,磕磕碰碰,只要运行起来了,谢天谢地然后不再折腾了,到下一次还需要部署时,这样的 ...
- JS键盘的键码(event.keyCode)
keycode 8 = BackSpace BackSpace keycode 9 = Tab Tab keycode 12 = Clear keycode 13 = Enter keycode 16 ...
- 洛谷 P1331 海战
传送门 题解:由于船是方形的,所以比较简单.但是考试的时候跪了,orz.忘了考虑类似一圈井号中间有一摊水. 可以只考虑这个点上方和左边点的情况,这样分为四种情况.一种是左边是一滩水, ...
- CLOUDSTACK HA功能,测试成功
要注意VM HA和HOST HA两个级别的区别.并且要整合.