博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Android】实现类似QQ列表
阅读量:4956 次
发布时间:2019-06-12

本文共 7230 字,大约阅读时间需要 24 分钟。

                          作者:朱红的泪(V5)   

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

       豆子的灵感是来自于 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

posted on
2011-12-18 00:55 阅读(
...) 评论(
...)

转载于:https://www.cnblogs.com/zhuzhongdelei/archive/2011/12/18/2291554.html

你可能感兴趣的文章
GIS开发之计算四参数,七参数
查看>>
2016-2017-2 《Java程序设计》第3周学习总结
查看>>
富文本编辑器里提取简介--正则表达式替换标签
查看>>
CCF系列之字符串匹配(201409-3)
查看>>
xss payloads ----full
查看>>
CTF-rootme 题解之ELF - 0 protection && ELF - x86 Basic
查看>>
第二课+第三课 计算机系统概论
查看>>
模板的全特化与偏特化
查看>>
文件内容查询cat,tac,nl,more,less,head,tail,od
查看>>
2017年3月15日上午日志
查看>>
isqlplus的使用
查看>>
获取FileSystem
查看>>
CSS Float(浮动)
查看>>
js脚本同步、异步与延迟
查看>>
关于oracle表空间的扩容
查看>>
bzoj:1725: [Usaco2006 Nov]Corn Fields牧场的安排
查看>>
GMA Round 1 空降
查看>>
iview carousel 图片不显示;iview 轮播图 图片无法显示(转载)
查看>>
Spring声明式事务为何不回滚
查看>>
利用Idea重构功能及Java8语法特性——优化深层嵌套代码
查看>>