当前位置: 代码迷 >> Android >> 2013.01.03 (二)——— android开发实例之仿QQExpandableListView
  详细解决方案

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

热度:198   发布时间:2016-04-28 07:01:56.0
2013.01.03 (2)——— android开发实例之仿QQExpandableListView
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 implements		OnScrollListener, 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	 * 是画上去的 , 所以设置事件监听是无效的 , 只有自行控制 .	 */	@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 = (IphoneTreeHeaderAdapter) adapter;	}	/**	 * 	 * 点击了 Group 触发的事件 , 要根据根据当前点击 Group 的状态来	 */	@Override	public 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;	}	@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.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());		}	}	@Override	public 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);	}	@Override	public void onScrollStateChanged(AbsListView view, int scrollState) {		if(mOnScrollListener!=null){			mOnScrollListener.onScrollStateChanged(view, scrollState);		}	}			@Override	public 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;	@Override	protected 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 BaseExpandableListAdapter			implements 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 stub			groupStatusMap = 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;		}		@Override		public View getChildView(int groupPosition, int childPosition,				boolean isLastChild, View convertView, ViewGroup parent) {			// TODO Auto-generated method stub			if (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;		}		@Override		public View getGroupView(int groupPosition, boolean isExpanded,				View convertView, ViewGroup parent) {			// TODO Auto-generated method stub			if (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;		}		@Override		public 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;			}		}		@Override		public 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);		}		@Override		public void onHeadViewClick(int groupPosition, int status) {			// TODO Auto-generated method stub			groupStatusMap.put(groupPosition, status);		}		@Override		public int getHeadViewClickStatus(int groupPosition) {			if (groupStatusMap.containsKey(groupPosition)) {				return groupStatusMap.get(groupPosition);			} else {				return 0;			}		}	}}



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






  相关解决方案