2013.01.03 (2)——— android开发实例之仿QQExpandableListView
参考:http://blog.csdn.net/way_ping_li/article/details/9090793


自定义的ExpandableListView
package com.example.testiphonetreeview;import android.content.Context;import android.graphics.Canvas;import android.util.AttributeSet;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;public class IphoneTreeView extends ExpandableListView implementsOnScrollListener, OnGroupClickListener {public IphoneTreeView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);registerListener();}public IphoneTreeView(Context context, AttributeSet attrs) {super(context, attrs);registerListener();}public IphoneTreeView(Context context) {super(context);registerListener();}/** * Adapter 接口 . 列表必须实现此接口 . */public interface IphoneTreeHeaderAdapter {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 getTreeHeaderState(int groupPosition, int childPosition);/** * 配置 QQHeader, 让 QQHeader 知道显示的内容 *  * @param header * @param groupPosition * @param childPosition * @param alpha */void configureTreeHeader(View header, int groupPosition,int childPosition, int alpha);/** * 设置组按下的状态 *  * @param groupPosition * @param status */void onHeadViewClick(int groupPosition, int status);/** * 获取组按下的状态 *  * @param groupPosition * @return */int getHeadViewClickStatus(int groupPosition);}private static final int MAX_ALPHA = 160;private IphoneTreeHeaderAdapter mAdapter;/** * 用于在列表头显示的 View,mHeaderViewVisible 为 true 才可见 */private View mHeaderView;/** * 列表头是否可见 */private boolean mHeaderViewVisible;private int mHeaderViewWidth;private int mHeaderViewHeight;private OnScrollListener mOnScrollListener;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() {super.setOnScrollListener(this);setOnGroupClickListener(this);}/** * 点击 HeaderView 触发的事件 */private void headerViewClick() {long packedPosition = getExpandableListPosition(this.getFirstVisiblePosition());int groupPosition = ExpandableListView.getPackedPositionGroup(packedPosition);if (mAdapter.getHeadViewClickStatus(groupPosition) == 1) {this.collapseGroup(groupPosition);mAdapter.onHeadViewClick(groupPosition, 0);} else {this.expandGroup(groupPosition);mAdapter.onHeadViewClick(groupPosition, 1);}this.setSelectedGroup(groupPosition);}private float mDownX;private float mDownY;/** * 如果 HeaderView 是可见的 , 此函数用于判断是否点击了 HeaderView, 并对做相应的处理 , 因为 HeaderView * 是画上去的 , 所以设置事件监听是无效的 , 只有自行控制 . */@Overridepublic 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);}@Overridepublic void setAdapter(ExpandableListAdapter adapter) {super.setAdapter(adapter);mAdapter = (IphoneTreeHeaderAdapter) adapter;}/** *  * 点击了 Group 触发的事件 , 要根据根据当前点击 Group 的状态来 */@Overridepublic boolean onGroupClick(ExpandableListView parent, View v,int groupPosition, long id) {if (mAdapter.getHeadViewClickStatus(groupPosition) == 0) {parent.expandGroup(groupPosition);mAdapter.onHeadViewClick(groupPosition, 1);} else if (mAdapter.getHeadViewClickStatus(groupPosition) == 1) {parent.collapseGroup(groupPosition);mAdapter.onHeadViewClick(groupPosition, 0);}return true;}@Overrideprotected 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;@Overrideprotected 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.getTreeHeaderState(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.getTreeHeaderState(groupPosition, childPosition);switch (state) {case IphoneTreeHeaderAdapter.PINNED_HEADER_GONE: {mHeaderViewVisible = false;break;}case IphoneTreeHeaderAdapter.PINNED_HEADER_VISIBLE: {mAdapter.configureTreeHeader(mHeaderView, groupPosition,childPosition, MAX_ALPHA);if (mHeaderView.getTop() != 0) {mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight);}mHeaderViewVisible = true;break;}case IphoneTreeHeaderAdapter.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.configureTreeHeader(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, getDrawingTime());}}@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {if(mOnScrollListener!=null){mOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);}final long flatPos = getExpandableListPosition(firstVisibleItem);int groupPosition = ExpandableListView.getPackedPositionGroup(flatPos);int childPosition = ExpandableListView.getPackedPositionChild(flatPos);System.out.println("onScroll=============groupPosition: " + groupPosition + ", childPosition: " + childPosition);configureHeaderView(groupPosition, childPosition);}@Overridepublic void onScrollStateChanged(AbsListView view, int scrollState) {if(mOnScrollListener!=null){mOnScrollListener.onScrollStateChanged(view, scrollState);}}@Overridepublic void setOnScrollListener(OnScrollListener l) {mOnScrollListener = l;}}



MainActivity.java

package com.example.testiphonetreeview;import java.util.HashMap;import android.app.Activity;import android.os.Bundle;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseExpandableListAdapter;import android.widget.ImageView;import android.widget.TextView;import com.example.testiphonetreeview.IphoneTreeView.IphoneTreeHeaderAdapter;public class MainActivity extends Activity {private IphoneTreeView iphoneTreeView;  private LayoutInflater mInflater;  private IphoneTreeViewAdapter mAdp;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();}private void initView(){mInflater = LayoutInflater.from(this);  iphoneTreeView = (IphoneTreeView) findViewById(R.id.iphone_tree_view);          iphoneTreeView.setHeaderView(getLayoutInflater().inflate(                  R.layout.contact_buddy_list_group, iphoneTreeView, false));          iphoneTreeView.setGroupIndicator(null);         mAdp = new IphoneTreeViewAdapter();        iphoneTreeView.setAdapter(mAdp);}public class IphoneTreeViewAdapter extends BaseExpandableListAdapterimplements IphoneTreeHeaderAdapter {// Sample data set. children[i] contains the children (String[]) for// groups[i].private HashMap<Integer, Integer> groupStatusMap;private String[] groups = { "第一组", "第二组", "第三组", "第四组", "第五组", "第六组", "第七组", "第八组" };private String[][] children = {{ "Way", "Arnold", "Barry", "Chuck", "David", "Afghanistan","Albania", "Belgium", "Lily", "Jim", "LiMing", "Jodan" },{ "Ace", "Bandit", "Cha-Cha", "Deuce", "Bahamas", "China","Dominica", "Jim", "LiMing", "Jodan" },{ "Fluffy", "Snuggles", "Ecuador", "Ecuador", "Jim", "LiMing","Jodan" },{ "Goldy", "Bubbles", "Iceland", "Iran", "Italy", "Jim","LiMing", "Jodan" },{ "Goldy", "Bubbles", "Iceland", "Iran", "Italy", "Jim","LiMing", "Jodan" },{ "Goldy", "Bubbles", "Iceland", "Iran", "Italy", "Jim","LiMing", "Jodan" },{ "Goldy", "Bubbles", "Iceland", "Iran", "Italy", "Jim","LiMing", "Jodan" },{ "Fluffy", "Bubbles", "Iceland", "Iran", "Italy", "Jim","LiMing", "Snuggles" }};public IphoneTreeViewAdapter() {// TODO Auto-generated constructor stubgroupStatusMap = new HashMap<Integer, Integer>();}public Object getChild(int groupPosition, int childPosition) {return children[groupPosition][childPosition];}public long getChildId(int groupPosition, int childPosition) {return childPosition;}public int getChildrenCount(int groupPosition) {return children[groupPosition].length;}public Object getGroup(int groupPosition) {return groups[groupPosition];}public int getGroupCount() {return groups.length;}public long getGroupId(int groupPosition) {return groupPosition;}public boolean isChildSelectable(int groupPosition, int childPosition) {return true;}public boolean hasStableIds() {return true;}@Overridepublic View getChildView(int groupPosition, int childPosition,boolean isLastChild, View convertView, ViewGroup parent) {// TODO Auto-generated method stubif (convertView == null) {convertView = mInflater.inflate(R.layout.contact_list_item_for_buddy, null);}TextView tv = (TextView) convertView.findViewById(R.id.contact_list_item_name);tv.setText(getChild(groupPosition, childPosition).toString());TextView state = (TextView) convertView.findViewById(R.id.cpntact_list_item_state);state.setText("爱生活...爱Android...");return convertView;}@Overridepublic View getGroupView(int groupPosition, boolean isExpanded,View convertView, ViewGroup parent) {// TODO Auto-generated method stubif (convertView == null) {convertView = mInflater.inflate(R.layout.contact_buddy_list_group, null);}TextView groupName = (TextView) convertView.findViewById(R.id.group_name);groupName.setText(groups[groupPosition]);ImageView indicator = (ImageView) convertView.findViewById(R.id.group_indicator);TextView onlineNum = (TextView) convertView.findViewById(R.id.online_count);onlineNum.setText(getChildrenCount(groupPosition) + "/"+ getChildrenCount(groupPosition));if (isExpanded) {indicator.setImageResource(R.drawable.indicator_expanded);} else {indicator.setImageResource(R.drawable.indicator_unexpanded);}return convertView;}@Overridepublic int getTreeHeaderState(int groupPosition, int childPosition) {final int childCount = getChildrenCount(groupPosition);System.out.println("getTreeHeaderState=============groupPosition: " + groupPosition + ", childPosition: " + childPosition + ", childCount: " + childCount);if (childPosition == childCount - 1) {System.out.println("=================PINNED_HEADER_PUSHED_UP======================");return PINNED_HEADER_PUSHED_UP;} else if (childPosition == -1&& !iphoneTreeView.isGroupExpanded(groupPosition)) {System.out.println("=================PINNED_HEADER_GONE======================");return PINNED_HEADER_GONE;} else {System.out.println("=================PINNED_HEADER_VISIBLE======================");return PINNED_HEADER_VISIBLE;}}@Overridepublic void configureTreeHeader(View header, int groupPosition,int childPosition, int alpha) {// TODO Auto-generated method stub((TextView) header.findViewById(R.id.group_name)).setText(groups[groupPosition]);((TextView) header.findViewById(R.id.online_count)).setText(getChildrenCount(groupPosition) + "/"+ getChildrenCount(groupPosition));header.getBackground().setAlpha(alpha);}@Overridepublic void onHeadViewClick(int groupPosition, int status) {// TODO Auto-generated method stubgroupStatusMap.put(groupPosition, status);}@Overridepublic int getHeadViewClickStatus(int groupPosition) {if (groupStatusMap.containsKey(groupPosition)) {return groupStatusMap.get(groupPosition);} else {return 0;}}}}



布局文件就不贴了,会附上源码,效果图如下



2013.01.03 (2)——— android开发实例之仿QQExpandableListView


更多相关文章

  1. 监听屏幕旋转事件
  2. Android 如何调用MediaPlayer播放视频[状态机]【图】
  3. android 安卓事件处理示例
  4. Android——ImageButton【图片按钮】的点击事件与属性
  5. Android 事件分发机制
  6. Android一个textview显示多段文本不同颜色并可以响应点击事件
  7. Android Studio中如何隐藏顶部状态栏和标题栏
  8. Android事件机制之二:onTouch详解
  9. Android中去除标题,全屏,获得屏幕方向及键盘状态

随机推荐

  1. Android(安卓)ViewFlipper瑁呰浇baseAdap
  2. android颜色对应的xml配置值,颜色表
  3. android sqlite和listview 使用小例子
  4. android键盘事件
  5. Android(安卓)ToggleButton控件的用法
  6. 重装Ubuntu13.04后需要做的事情
  7. 日拱一卒(十三)
  8. android 保存配置文档
  9. 《android上传图片》
  10. andorid 自定义seekbar