Before the implementation of this effect of the expandablelistview:http://www.jb51.net/article/38482.htm, with the effect of a setback, recently, in the reference contact source Pinnedheaderlistview, As well as online heroes of the source code, encapsulation of a best effect, and the use of the simplest iphonetreeview, the following first look at the effect map:
First let's take a look at the Iphonetreeview that are packaged better:
Copy Code code as follows:
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 {
Super (context);
Registerlistener ();
}
/**
* Adapter interface. The list must implement this interface.
*/
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;
/**
* Get the status of Header
*
* @param groupposition
* @param childposition
* @return
* PINNED_HEADER_GONE,PINNED_HEADER_VISIBLE,PINNED_HEADER_PUSHED_UP
* One of them
*/
int gettreeheaderstate (int groupposition, int childposition);
/**
* Configure Qqheader to let Qqheader know what is displayed
*
* @param header
* @param groupposition
* @param childposition
* @param Alpha
*/
void Configuretreeheader (View header, int groupposition,
int childposition, int alpha);
/**
* Set the status of the group pressed
*
* @param groupposition
* @param status
*/
void Onheadviewclick (int groupposition, int status);
/**
* Get the group pressed status
*
* @param groupposition
* @return
*/
int getheadviewclickstatus (int groupposition);
}
private static final int max_alpha = 255;
Private Iphonetreeheaderadapter Madapter;
/**
* For the view,mheaderviewvisible displayed in the list header to be true to be visible
*/
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 on Headerview triggered event
*/
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;
/**
* If the Headerview is visible, this function is used to determine whether to click on the Headerview and to do the appropriate processing because Headerview
* is painted up, so set event monitoring is invalid, only self control.
*/
@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);
If the Headerview is visible, click inside the Headerview, then trigger 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;
}
/**
*
* Click on the group trigger event, depending on the status of the current click Group
*/
@Override
public Boolean Ongroupclick (expandablelistview parent, View V,
int groupposition, long id) {
if (Madapter.getheadviewclickstatus (groupposition) = = 0) {
Madapter.onheadviewclick (groupposition, 1);
Parent.expandgroup (groupposition);
Parent.setselectedgroup (groupposition);
else if (madapter.getheadviewclickstatus (groupposition) = = 1) {
Madapter.onheadviewclick (groupposition, 0);
Parent.collapsegroup (groupposition);
}
Returns true to bounce back to the first row, not knowing why
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
/**
* Call this method when the list interface is updated (for example, when scrolling)
*/
protected void Dispatchdraw (Canvas Canvas) {
Super.dispatchdraw (canvas);
if (mheaderviewvisible) {
The group bar is drawn directly into the interface, rather than being added to the viewgroup.
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) {
}
}
It is also relatively simple to use, first in the layout file to declare activity_main.xml:
Copy Code code as follows:
<relativelayout xmlns:android= "Http://schemas.android.com/apk/res/android"
Xmlns:tools= "Http://schemas.android.com/tools"
Android:layout_width= "Match_parent"
android:layout_height= "Match_parent"
Tools:context= ". Mainactivity ">
<com.way.iphonetreeview.iphonetreeview
Android:id= "@+id/iphone_tree_view"
Android:layout_width= "Match_parent"
android:layout_height= "Match_parent"
Android:background= "@android: Color/transparent"
Android:cachecolorhint= "@android: Color/transparent"
Android:divider= "@null"
Android:transcriptmode= "Normal"/>
</RelativeLayout>
And then called in Mainactivity, in order to reduce the code, I put adapter as an inner class in the mainactivity:
Copy Code code as follows:
public class Mainactivity extends activity {
Private Layoutinflater Minflater;
Private Iphonetreeview Iphonetreeview;
@Override
protected void OnCreate (Bundle savedinstancestate) {
Super.oncreate (savedinstancestate);
Setcontentview (R.layout.activity_main);
Initview ();
}
private void Initview () {
TODO auto-generated Method Stub
Minflater = Layoutinflater.from (this);
Iphonetreeview = (Iphonetreeview) Findviewbyid (R.id.iphone_tree_view);
Iphonetreeview.setheaderview (Getlayoutinflater (). Inflate (
R.layout.list_head_view, Iphonetreeview, false));
Iphonetreeview.setgroupindicator (NULL);
Iphonetreeview.setadapter (New Iphonetreeviewadapter ());
}
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 = {"First group", "second group", "third group", "fourth Group"};
Private string[][] Children = {
{"Way", "Arnold", "Barry", "Chuck", "David", "Afghanistan",
"Albania", "Belgium", "Lily", "Jim", "Liming", "Jodan"},
{"Ace", "Bandit", "Cha-Cha", "Deuce", "Bahamas", "a",
"Dominica", "Jim", "Liming", "Jodan"},
{"Fluffy", "snuggles", "Ecuador", "Ecuador", "Jim", "Liming",
"Jodan"},
{"Goldy", "Bubbles", "Iceland", "Iran", "Italy", "Jim",
"Liming", "Jodan"}};
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.list_item_view, 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 ("Love life ...") Love 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.list_group_view, 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);
if (childposition = = childCount-1) {
return pinned_header_pushed_up;
else if (childposition = 1
&&!iphonetreeview.isgroupexpanded (groupposition)) {
return pinned_header_gone;
} else {
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));
}
@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;
}
}
}
}
Well, a simple example is done,
To sum up:
Principle: Add a view that is exactly the same as the group view in the label position of the topmost group that is being displayed as a group label. The position of the label changes with the slide of the list to keep it always displayed at the top and disappear when it disappears. Add Click events to this tab to enable the ability to turn grouping on and off.
The group label is always displayed above, which is achieved by constantly adjusting its position in the layout. This adjustment process, in the initialization, in the OnLayout method to implement once, followed by the rolling process, according to the rolling state of the monitoring to achieve.
When instantiating the label to be added (implemented outside, even before calling Settreeheaderview), parent is set to the Expandablelistview.
The best way to learn and understand this is to make the added group label translucent to facilitate the observation of the entire process.
SOURCE download