[转载]Android实现类似QQ列表

[转载]【Android】实现类似QQ列表 – 朱红的泪 – 博客园.

感谢豆子兄弟的指点 . 本文是参照他的代码在经过一点改造 .

豆子的灵感是来自于 Google 的 Contacts( 联系人 ) 的实现 , 其中有一个类叫做 PinnedHeaderListView( 固定头的列表),本文也不做过多的解释,因为Google的程序中已经写得很清楚了.

本列表是根据自己需要专门实现类似于QQ列表的功能,所以可能扩展性不是很强,自己满足就好.

QQ: 列表显示效果

/**

* QQ 列表

* @author 朱红的泪 (V5)

*

*/

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, float height) {

mHeaderView = view;

AbsListView.LayoutParams lp = new AbsListView.LayoutParams(

ViewGroup.LayoutParams. MATCH_PARENT , ( int ) height);

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

// 没设置这个会出现一些奇怪的问题 , 暂时不知道为什么

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 ) {

drawChild(canvas, mHeaderView , getDrawingTime());

}

}

@Override

public void onScroll(AbsListView view, int firstVisibleItem,

int visibleItemCount, int totalItemCount) {

final long flatPos = getExpandableListPosition(firstVisibleItem);

int groupPosition = ExpandableListView.getPackedPositionGroup(flatPos);

int childPosition = ExpandableListView.getPackedPositionChild(flatPos);

configureHeaderView(groupPosition, childPosition);

}

@Override

public void onScrollStateChanged(AbsListView view, int scrollState) {

}

}

邮箱:weiwutan@gmail.com

赞(0) 打赏
分享到: 更多 (0)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏