Effect of Android UI view-imitation QQ friends list group floating PinnedHeaderExpandableListView
I tested it on a tablet. The picture is a little big. You can check the effect.
Next, paste the source code:
PinnedHeaderExpandableListView. java
Note that in the onGroupClick method, the function of the Code parent. setSelectedGroup (groupPosition) is to click the group top,
I don't need this effect on this side, and QQ does not use it, so I have commented on it. If you need it, you can unlock the comment.
Package com. xiaos. view; 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. expa NdableListView. extends; public class extends ExpandableListView implements OnScrollListener, listener {public listener (Context context, AttributeSet attrs, int defStyle) {super (context, attrs, defStyle); registerListener ();} public PinnedHeaderExpandableListView (Context context, AttributeSet attrs) {super (context, attrs); reg IsterListener ();} public PinnedHeaderExpandableListView (Context context) {super (context); registerListener ();}/*** Adapter interface. the list must implement this interface. */public interface HeaderAdapter {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; /*** get the Header status * @ param groupPosition * @ param childPosition * @ return PI NNED_HEADER_GONE, PINNED_HEADER_VISIBLE, one of PINNED_HEADER_PUSHED_UP */int getHeaderState (int groupPosition, int childPosition);/*** configure the Header, let the Header know the displayed content * @ param header * @ param groupPosition * @ param childPosition * @ param alpha */void configureHeader (View header, int groupPosition, int childPosition, int alpha ); /*** set the group press status * @ param groupPosition * @ param status */void setGroupClickStat Us (int groupPosition, int status);/*** get the group press status * @ param groupPosition * @ return */int getGroupClickStatus (int groupPosition );} private static final int MAX_ALPHA = 255; private HeaderAdapter mAdapter;/*** is used to display the View in the list header. mHeaderViewVisible is true. */private View mHeaderView; /*** whether the list header is visible */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 );} /*** click the event triggered by HeaderView */private void headerViewClick () {long packedPosition = getExpandableListPosition (this. getFirstVisiblePosition (); int groupPosition = ExpandableListView. getPackedPositionGroup (packedPosition); if (mAdapter. getGroupClickStatus (groupPosit Ion) = 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;/*** if HeaderView is visible, this function is used to determine whether HeaderView has been clicked and handle the problem accordingly, * Because HeaderView is drawn, setting event listening is invalid and only self-controlled. * // @ Overridepublic boolean UchEvent (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); // If HeaderView is visible, click In rView, 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 = (HeaderAdapter) adapter;}/***** click the event triggered by Group, */@ Overridepublic boolean onGroupClick (ExpandableListView parent, View v, int groupPosition, long id) {if (mAdapter. getGroupClickStatus (g RoupPosition) = 0) {mAdapter. setGroupClickStatus (groupPosition, 1); parent. expandGroup (groupPosition); // the Header is automatically set to the top // parent. setSelectedGroup (groupPosition);} else if (mAdapter. getGroupClickStatus (groupPosition) = 1) {mAdapter. setGroupClickStatus (groupPosition, 0); parent. collapseGroup (groupPosition);} // return true to play back the first row. I don't know why return true;} @ Overrideprotected void onMeasure (int widthMeasureSpec, in T 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 (getFi RstVisiblePosition (); final int groupPos = ExpandableListView. getPackedPositionGroup (flatPostion); final int childPos = ExpandableListView. getPackedPositionChild (flatPostion); int state = mAdapter. getHeaderState (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. getHeaderState (groupPosition, childPosition); switch (state ){ Case HeaderAdapter. Handle: {mHeaderViewVisible = false; break;} case HeaderAdapter. Handle: {mAdapter. configureHeader (mHeaderView, groupPosition, childPosition, MAX_ALPHA); if (mHeaderView. getTop ()! = 0) {mHeaderView. layout (0, 0, mHeaderViewWidth, mHeaderViewHeight);} mHeaderViewVisible = true; break;} case HeaderAdapter. 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
PinnedHeaderExpandableAdapter. java Adapter
Implemented the HeaderAdapter interface in PinnedHeaderExpandableListView
package com.xiaos.adapter;import android.content.Context;import android.util.SparseIntArray;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.xiaos.pinnedheaderexpandable.R;import com.xiaos.view.PinnedHeaderExpandableListView;import com.xiaos.view.PinnedHeaderExpandableListView.HeaderAdapter;public class PinnedHeaderExpandableAdapter extends BaseExpandableListAdapter implements HeaderAdapter{private String[][] childrenData;private String[] groupData;private Context context;private PinnedHeaderExpandableListView listView;private LayoutInflater inflater;public PinnedHeaderExpandableAdapter(String[][] childrenData,String[] groupData,Context context,PinnedHeaderExpandableListView listView){this.groupData = groupData; this.childrenData = childrenData;this.context = context;this.listView = listView;inflater = LayoutInflater.from(this.context);}@Overridepublic Object getChild(int groupPosition, int childPosition) {return childrenData[groupPosition][childPosition];}@Overridepublic long getChildId(int groupPosition, int childPosition) {return 0;}@Overridepublic View getChildView(int groupPosition, int childPosition,boolean isLastChild, View convertView, ViewGroup parent) {View view = null; if (convertView != null) { view = convertView; } else { view = createChildrenView(); } TextView text = (TextView)view.findViewById(R.id.childto);text.setText(childrenData[groupPosition][childPosition]); return view; }@Overridepublic int getChildrenCount(int groupPosition) {return childrenData[groupPosition].length;}@Overridepublic Object getGroup(int groupPosition) {return groupData[groupPosition];}@Overridepublic int getGroupCount() {return groupData.length;}@Overridepublic long getGroupId(int groupPosition) {return 0;}@Overridepublic View getGroupView(int groupPosition, boolean isExpanded,View convertView, ViewGroup parent) {View view = null; if (convertView != null) { view = convertView; } else { view = createGroupView(); } ImageView iv = (ImageView)view.findViewById(R.id.groupIcon);if (isExpanded) {iv.setImageResource(R.drawable.btn_browser2);}else{iv.setImageResource(R.drawable.btn_browser);}TextView text = (TextView)view.findViewById(R.id.groupto);text.setText(groupData[groupPosition]); return view; }@Overridepublic boolean hasStableIds() {return true;}@Overridepublic boolean isChildSelectable(int groupPosition, int childPosition) {return true;}private View createChildrenView() {return inflater.inflate(R.layout.child, null);}private View createGroupView() {return inflater.inflate(R.layout.group, null);}@Overridepublic int getHeaderState(int groupPosition, int childPosition) {final int childCount = getChildrenCount(groupPosition);if (childPosition == childCount - 1) {return PINNED_HEADER_PUSHED_UP;} else if (childPosition == -1&& !listView.isGroupExpanded(groupPosition)) {return PINNED_HEADER_GONE;} else {return PINNED_HEADER_VISIBLE;}}@Overridepublic void configureHeader(View header, int groupPosition,int childPosition, int alpha) {String groupData = this.groupData[groupPosition];((TextView) header.findViewById(R.id.groupto)).setText(groupData);}private SparseIntArray groupStatusMap = new SparseIntArray(); @Overridepublic void setGroupClickStatus(int groupPosition, int status) {groupStatusMap.put(groupPosition, status);}@Overridepublic int getGroupClickStatus(int groupPosition) {if (groupStatusMap.keyAt(groupPosition)>=0) {return groupStatusMap.get(groupPosition);} else {return 0;}}}
MainActivity. java main Activity
Package com. xiaos. pinnedheaderexpandable; import android. app. activity; import android. OS. bundle; import android. view. view; import android. widget. expandableListView; import android. widget. expandableListView. onGroupClickListener; import com. xiaos. adapter. pinnedHeaderExpandableAdapter; import com. xiaos. view. pinnedHeaderExpandableListView; public class MainActivity extends Activity {private PinnedHeaderExpandableListView explistview; private String [] [] childrenData = new String [10] [10]; private String [] groupData = new String [10]; private int expandFlag =-1; // expand the private PinnedHeaderExpandableAdapter adapter; @ Overrideprotected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. layout_main); initView (); initData ();}/*** initialize VIEW */private void initView () {explistview = (PinnedHeaderExpandableListView) findViewById (R. id. explistview);}/*** initialization data */private void initData () {for (int I = 0; I <10; I ++) {groupData [I] = group + I;} for (int I = 0; I <10; I ++) {for (int j = 0; j <10; j ++) {childrenData [I] [j] = friend + I +-+ j ;}// sets the floating header VIEWexplistview. setHeaderView (getLayoutInflater (). inflate (R. layout. group_head, explistview, false); adapter = new PinnedHeaderExpandableAdapter (childrenData, groupData, getApplicationContext (), explistview); explistview. setAdapter (adapter); // you can specify whether to expand a single group. listener (new GroupClickListener ();} class GroupClickListener implements listener {@ Overridepublic boolean onGroupClick (partition parent, View v, int groupPosition, long id) {if (expandFlag =-1) {// expand the selected groupexplistview. expandGroup (groupPosition); // set the selected group to the top of the explicit view. setSelectedGroup (groupPosition); expandFlag = groupPosition;} else if (expandFlag = groupPosition) {explistview. collapseGroup (expandFlag); expandFlag =-1;} else {explistview. collapseGroup (expandFlag); // expand the selected groupexplistview. expandGroup (groupPosition); // set the selected group to the top of the explicit view. setSelectedGroup (groupPosition); expandFlag = groupPosition;} return true ;}}}
Layout File
Child. xml
Group_head.xml
Group. xml
Layout_main.xml
AndroidManifest. xml
Two images: