package com.iaiai;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ExpandableListAdapter;
import android.widget.ExpandableListView;
import android.widget.ExpandableListView.OnGroupClickListener;
import android.widget.ImageView;
import android.widget.TextView;
public class QQListView extends ExpandableListView implements OnScrollListener,OnGroupClickListener {
public QQListView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
registerListener();
}
public QQListView(Context context, AttributeSet attrs) {
super(context, attrs);
registerListener();
}
public QQListView(Context context) {
super(context);
registerListener();
}
/**
* Adapter 接口 . 列表必须实现此接口 .
*/
public interface QQHeaderAdapter {
public static final int PINNED_HEADER_GONE = 0;
public static final int PINNED_HEADER_VISIBLE = 1;
public static final int PINNED_HEADER_PUSHED_UP = 2;
/**
* 获取 Header 的状态
* @param groupPosition
* @param childPosition
* @return PINNED_HEADER_GONE,PINNED_HEADER_VISIBLE,PINNED_HEADER_PUSHED_UP 其中之一
*/
int getQQHeaderState(int groupPosition, int childPosition);
/**
* 配置 QQHeader, 让 QQHeader 知道显示的内容
* @param header
* @param groupPosition
* @param childPosition
* @param alpha
*/
void configureQQHeader(View header, int groupPosition,int childPosition, int alpha);
/**
* 设置组按下的状态
* @param groupPosition
* @param status
*/
void setGroupClickStatus(int groupPosition, int status);
/**
* 获取组按下的状态
* @param groupPosition
* @return
*/
int getGroupClickStatus(int groupPosition);
}
private static final int MAX_ALPHA = 255;
private QQHeaderAdapter mAdapter;
/**
* 用于在列表头显示的 View,mHeaderViewVisible 为 true 才可见
*/
private View mHeaderView;
/**
* 列表头是否可见
*/
private boolean mHeaderViewVisible;
private int mHeaderViewWidth;
private int mHeaderViewHeight;
public void setHeaderView(View view) {
mHeaderView = view;
AbsListView.LayoutParams lp = new AbsListView.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
view.setLayoutParams(lp);
if (mHeaderView != null) {
setFadingEdgeLength(0);
}
requestLayout();
}
private void registerListener() {
setOnScrollListener(this);
setOnGroupClickListener(this);
}
/**
* 点击 HeaderView 触发的事件
*/
private void headerViewClick() {
long packedPosition = getExpandableListPosition(this.getFirstVisiblePosition());
int groupPosition = ExpandableListView.getPackedPositionGroup(packedPosition);
if (mAdapter.getGroupClickStatus(groupPosition) == 1) {
this.collapseGroup(groupPosition);
mAdapter.setGroupClickStatus(groupPosition, 0);
}
else{
this.expandGroup(groupPosition);
mAdapter.setGroupClickStatus(groupPosition, 1);
}
this.setSelectedGroup(groupPosition);
}
private float mDownX;
private float mDownY;
/**
* 如果 HeaderView 是可见的 , 此函数用于判断是否点击了 HeaderView, 并对做相应的处理 ,
* 因为 HeaderView 是画上去的 , 所以设置事件监听是无效的 , 只有自行控制 .
*/
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (mHeaderViewVisible) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
mDownX = ev.getX();
mDownY = ev.getY();
if (mDownX <= mHeaderViewWidth && mDownY <= mHeaderViewHeight) {
return true;
}
break;
case MotionEvent.ACTION_UP:
float x = ev.getX();
float y = ev.getY();
float offsetX = Math.abs(x - mDownX);
float offsetY = Math.abs(y - mDownY);
// 如果 HeaderView 是可见的 , 点击在 HeaderView 内 , 那么触发 headerClick()
if (x <= mHeaderViewWidth && y <= mHeaderViewHeight
&& offsetX <= mHeaderViewWidth && offsetY <= mHeaderViewHeight) {
if (mHeaderView != null) {
headerViewClick();
}
return true;
}
break;
default:
break;
}
}
return super.onTouchEvent(ev);
}
@Override
public void setAdapter(ExpandableListAdapter adapter) {
super.setAdapter(adapter);
mAdapter = (QQHeaderAdapter) adapter;
}
/**
*
* 点击了 Group 触发的事件 , 要根据根据当前点击 Group 的状态来
*/
@Override
public boolean onGroupClick(ExpandableListView parent,View v,int groupPosition,long id) {
if (mAdapter.getGroupClickStatus(groupPosition) == 0) {
mAdapter.setGroupClickStatus(groupPosition, 1);
parent.expandGroup(groupPosition);
parent.setSelectedGroup(groupPosition);
} else if (mAdapter.getGroupClickStatus(groupPosition) == 1) {
mAdapter.setGroupClickStatus(groupPosition, 0);
parent.collapseGroup(groupPosition);
}
// 返回 true 才可以弹回第一行 , 不知道为什么
return true;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (mHeaderView != null) {
measureChild(mHeaderView, widthMeasureSpec, heightMeasureSpec);
mHeaderViewWidth = mHeaderView.getMeasuredWidth();
mHeaderViewHeight = mHeaderView.getMeasuredHeight();
}
}
private int mOldState = -1;
@Override
protected void onLayout(boolean changed, int left, int top, int right,int bottom) {
super.onLayout(changed, left, top, right, bottom);
final long flatPostion = getExpandableListPosition(getFirstVisiblePosition());
final int groupPos = ExpandableListView.getPackedPositionGroup(flatPostion);
final int childPos = ExpandableListView.getPackedPositionChild(flatPostion);
int state = mAdapter.getQQHeaderState(groupPos, childPos);
if (mHeaderView != null && mAdapter != null && state != mOldState) {
mOldState = state;
mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight);
}
configureHeaderView(groupPos, childPos);
}
public void configureHeaderView(int groupPosition, int childPosition) {
if (mHeaderView == null || mAdapter == null
|| ((ExpandableListAdapter) mAdapter).getGroupCount() == 0) {
return;
}
int state = mAdapter.getQQHeaderState(groupPosition, childPosition);
switch (state) {
case QQHeaderAdapter.PINNED_HEADER_GONE: {
mHeaderViewVisible = false;
break;
}
case QQHeaderAdapter.PINNED_HEADER_VISIBLE: {
mAdapter.configureQQHeader(mHeaderView, groupPosition,childPosition, MAX_ALPHA);
if (mHeaderView.getTop() != 0){
mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight);
}
mHeaderViewVisible = true;
break;
}
case QQHeaderAdapter.PINNED_HEADER_PUSHED_UP: {
View firstView = getChildAt(0);
int bottom = firstView.getBottom();
// intitemHeight = firstView.getHeight();
int headerHeight = mHeaderView.getHeight();
int y;
int alpha;
if (bottom < headerHeight) {
y = (bottom - headerHeight);
alpha = MAX_ALPHA * (headerHeight + y) / headerHeight;
} else {
y = 0;
alpha = MAX_ALPHA;
}
mAdapter.configureQQHeader(mHeaderView, groupPosition,childPosition, alpha);
if (mHeaderView.getTop() != y) {
mHeaderView.layout(0, y, mHeaderViewWidth, mHeaderViewHeight + y);
}
mHeaderViewVisible = true;
break;
}
}
}
@Override
/**
* 列表界面更新时调用该方法(如滚动时)
*/
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (mHeaderViewVisible) {
//分组栏是直接绘制到界面中,而不是加入到ViewGroup中
drawChild(canvas, mHeaderView, getDrawingT
没有合适的资源?快使用搜索试试~ 我知道了~
完美ExpandableListView仿QQ列表,可扩展性强
共52个文件
png:18个
class:12个
xml:8个
5星 · 超过95%的资源 需积分: 9 55 下载量 75 浏览量
2013-06-11
17:51:12
上传
评论 3
收藏 716KB ZIP 举报
温馨提示
ExpandableListView仿QQ列表点击group上弹置顶效果,非常完美
资源推荐
资源详情
资源评论
收起资源包目录
ExpandableListDemo.zip (52个子文件)
ExpandableListDemo
bin
classes.dex 12KB
res
drawable-ldpi
ic_launcher.png 2KB
drawable-hdpi
btn_browser.png 1KB
default_bg.png 111KB
btn_browser2.png 1KB
ic_launcher.png 4KB
user_group.png 3KB
child_image.png 2KB
drawable-mdpi
ic_launcher.png 2KB
ExpandableListDeamo.apk 147KB
jarlist.cache 119B
classes
com
iaiai
MainActivity.class 2KB
BuildConfig.class 327B
R$layout.class 461B
R$id.class 469B
R$drawable.class 676B
QQListView$QQHeaderAdapter.class 522B
R$attr.class 313B
QQListView.class 6KB
R.class 507B
R$string.class 400B
QQListAdapter.class 4KB
R$color.class 363B
resources.ap_ 138KB
ExpandableListDemo.apk 147KB
res
drawable-ldpi
ic_launcher.png 2KB
drawable-hdpi
btn_browser.png 1KB
default_bg.png 111KB
expander_ic_maximized.9.png 2KB
btn_browser2.png 2KB
ic_launcher.png 4KB
user_group.png 3KB
child_image.png 2KB
expander_ic_minimized.9.png 2KB
drawable
qq_arrow.xml 271B
values
strings.xml 198B
color.xml 105B
drawable-mdpi
ic_launcher.png 3KB
layout
child.xml 715B
group.xml 742B
main.xml 904B
group_header.xml 752B
assets
gen
com
iaiai
BuildConfig.java 151B
R.java 2KB
proguard.cfg 1KB
.settings
src
com
iaiai
QQListAdapter.java 3KB
QQListView.java 8KB
MainActivity.java 2KB
.project 854B
.classpath 364B
project.properties 361B
AndroidManifest.xml 720B
共 52 条
- 1
ransimon
- 粉丝: 0
- 资源: 5
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- Wireshark-4.2.4-x64.zip
- 2022年11月软件设计师上
- 基于VB+ACCESS教学管理系统(参考文献+源代码).zip
- 一个工具的流程图 demo
- EMC3080的用于连接FogCloud的固件
- 基于VB+Access酒店客房管理系统(源代码+参考文献+报告).zip
- 应用笔记LAT1244+奇怪的NRST+管脚异常复位问题
- SEMI标准的解释说明
- tensorflow-2.8.2-cp37-cp37m-manylinux2010-x86-64.whl
- tensorflow-rocm-2.12.0.560-cp311-cp311-manylinux2014-x86-64.whl
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
- 1
- 2
- 3
前往页