In the previous article "Android custom components series [5] -- advanced practice (1)", the previous section of "Implementation of the drop-down PinnedHeaderExpandableListView" of Ren's "Implementation of PinnedHeaderExpandableListView" was implemented, in this article, let's take a look at the use of ExpandableListView and implement the rest.
Source: http://blog.csdn.net/singwhatiwanna/article/details/25546871
I. Usage of ExpandableListView
ExpandableListView is a subclass of ListView. It is extended based on a common ListView and the adapter is ExpandableListAdapter.
Similar to Adapter, ExpandableListAdapter can be implemented as follows:
1. Extended BaseExpandableListAdapter to implement ExpandableListAdapter
2. Use SimpleExpandableListAdapter to wrap two List sets into ExpandableListAdapter
3. Use SimpleCursorTreeAdapter to package data in Cursor into SimpleCursorTreeAdapter
Next we will use the first method to make a small example to see how to use ExpandableListView.
ExpandableListAdapter adapter = new BaseExpandableListAdapter() {@Overridepublic boolean isChildSelectable(int arg0, int arg1) {// TODO Auto-generated method stubreturn false;}@Overridepublic boolean hasStableIds() {// TODO Auto-generated method stubreturn false;}@Overridepublic View getGroupView(int arg0, boolean arg1, View arg2, ViewGroup arg3) {// TODO Auto-generated method stubreturn null;}@Overridepublic long getGroupId(int arg0) {// TODO Auto-generated method stubreturn 0;}@Overridepublic int getGroupCount() {// TODO Auto-generated method stubreturn 0;}@Overridepublic Object getGroup(int arg0) {// TODO Auto-generated method stubreturn null;}@Overridepublic int getChildrenCount(int arg0) {// TODO Auto-generated method stubreturn 0;}@Overridepublic View getChildView(int arg0, int arg1, boolean arg2, View arg3,ViewGroup arg4) {// TODO Auto-generated method stubreturn null;}@Overridepublic long getChildId(int arg0, int arg1) {// TODO Auto-generated method stubreturn 0;}@Overridepublic Object getChild(int arg0, int arg1) {// TODO Auto-generated method stubreturn null;}};
We can see that there are many methods in BaseExpandableListApdater. The main methods are described as follows:
GetGroupCount (): number of returned Group lists
GetGroupView (): The returned View is used as the group list item.
GetChildrenCount (): returns the number of sub-list items.
GetChildView (): The returned View is a sub-list item in a specific group or location.
Package com. example. expandablelistviewtest; import android. app. activity; import android. OS. bundle; import android. view. gravity; import android. view. view; import android. view. viewGroup; import android. widget. absListView; import android. widget. baseExpandableListAdapter; import android. widget. expandableListAdapter; import android. widget. expandableListView; import android. widget. imageView; import android. widget. linearLayout; import android. widget. textView; public class MainActivity extends Activity {@ Overrideprotected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_main); ExpandableListAdapter adapter = new BaseExpandableListAdapter () {int [] logos = new int [] {R. drawable. ic_launcher, R. drawable. ic_launcher, R. drawable. ic_launcher}; private String [] groupTypes = new String [] {"computer language", "human language", "animal language "}; private String [] [] childTypes = new String [] [] {"Java", "C ++", "C", "PHP" },{ "Chinese ", "English", "Japanese", "French" },{ "cool", "Wang", ""}}; // obtain the sub-list item data at the specified group position and specified sub-list item @ Overridepublic Object getChild (int groupPosition, int childPosition) {return childTypes [groupPosition] [childPosition];} @ Overridepublic long getChildId (int groupPosition, int childPosition) {return childPosition;} @ Overridepublic int getChildrenCount (int groupPosition) {return childTypes [groupPosition]. length;} private TextView getTextView () {AbsListView. layoutParams lp = new AbsListView. layoutParams (ViewGroup. layoutParams. MATCH_PARENT, 64); TextView textView = new TextView (MainActivity. this); textView. setLayoutParams (lp); textView. setGravity (Gravity. CENTER_VERTICAL | Gravity. LEFT); textView. setPadding (36, 0, 0, 0); textView. setTextSize (20); return textView;} // This method determines the appearance of each sub-option @ Overridepublic View getChildView (int groupPosition, int childPosition, boolean isLastChild, View convertView, ViewGroup parent) {TextView textView = getTextView (); textView. setText (getChild (groupPosition, childPosition ). toString (); return textView;} // obtain the group data at the specified group position @ Overridepublic Object getGroup (int groupPosition) {return groupTypes [groupPosition];} @ Overridepublic int getGroupCount () {return groupTypes. length ;}@ Overridepublic long getGroupId (int groupPosition) {return groupPosition;} // This method determines the appearance of each group of options @ Overridepublic View getGroupView (int groupPosition, boolean isExpanded, View convertView, viewGroup parent) {LinearLayout ll = new LinearLayout (MainActivity. this); ll. setOrientation (0); ImageView logo = new ImageView (MainActivity. this); logo. setImageResource (logos [groupPosition]); ll. addView (logo); TextView textView = getTextView (); textView. setText (getGroup (groupPosition ). toString (); ll. addView (textView); return ll ;}@ Overridepublic boolean isChildSelectable (int groupPosition, int childPosition) {return true ;}@ Overridepublic boolean hasStableIds () {return true ;}}; expandableListView expandListView = (ExpandableListView) findViewById (R. id. list); expandListView. setAdapter (adapter );}}
<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" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" ><ExpandableListView android:id="@+id/list" android:layout_width="match_parent" android:layout_height="wrap_content"/></RelativeLayout>
Ii. Code Analysis
First, let's look at the onCreate method:
@ Override public void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. main); expandableListView = (PinnedHeaderExpandableListView) findViewById (R. id. expandablelist); stickyLayout = (StickyLayout) findViewById (R. id. sticky_layout); initData (); adapter = new MyexpandableListAdapter (this); expandableListView. setAdapter (adapter); // expand all groups for (int I = 0, count = expandableListView. getCount (); I <count; I ++) {expandableListView. expandGroup (I);} expandableListView. setOnHeaderUpdateListener (this); expandableListView. setOnChildClickListener (this); expandableListView. setOnGroupClickListener (this); stickyLayout. setOnGiveUpTouchEventListener (this );}
The previous lines are very easy. Just like the example above, we only need to pay attention to the initData () method and the following listening functions.
InitData () is the simulated data, as follows:
void initData() { groupList = new ArrayList<Group>(); Group group = null; for (int i = 0; i < 3; i++) { group = new Group(); group.setTitle("group-" + i); groupList.add(group); } childList = new ArrayList<List<People>>(); for (int i = 0; i < groupList.size(); i++) { ArrayList<People> childTemp; if (i == 0) { childTemp = new ArrayList<People>(); for (int j = 0; j < 13; j++) { People people = new People(); people.setName("yy-" + j); people.setAge(30); people.setAddress("sh-" + j); childTemp.add(people); } } else if (i == 1) { childTemp = new ArrayList<People>(); for (int j = 0; j < 8; j++) { People people = new People(); people.setName("ff-" + j); people.setAge(40); people.setAddress("sh-" + j); childTemp.add(people); } } else { childTemp = new ArrayList<People>(); for (int j = 0; j < 23; j++) { People people = new People(); people.setName("hh-" + j); people.setAge(20); people.setAddress("sh-" + j); childTemp.add(people); } } childList.add(childTemp); } }
Next, let's look at the listening functions.
public class MainActivity extends Activity implements ExpandableListView.OnChildClickListener, ExpandableListView.OnGroupClickListener, OnHeaderUpdateListener, OnGiveUpTouchEventListener {
From the inheritance relationship of the Activity, OnChildClickListener and OnGroupClickListener are listener functions of the ExpandableListView class.
@Override public boolean onGroupClick(final ExpandableListView parent, final View v, int groupPosition, final long id) { return false; } @Override public boolean onChildClick(ExpandableListView parent, View v, int groupPosition, int childPosition, long id) { Toast.makeText(MainActivity.this, childList.get(groupPosition).get(childPosition).getName(), 1) .show(); return false; }
Let's take a look at OnHeaderUpdateListener. This listener function is actually a custom listener in the overwrite (custom) ExpandableListView.
public void setOnHeaderUpdateListener(OnHeaderUpdateListener listener) { mHeaderUpdateListener = listener; if (listener == null) { return; } mHeaderView = listener.getPinnedHeader(); int firstVisiblePos = getFirstVisiblePosition(); int firstVisibleGroupPos = getPackedPositionGroup(getExpandableListPosition(firstVisiblePos)); listener.updatePinnedHeader(firstVisibleGroupPos); requestLayout(); postInvalidate(); }
The getPinnedHeader () method creates (obtains) a list header, and then sets the group name of the currently visible sub-list element through the updatePinnedHeader method.
The requestLayout () method is used when the view determines that it is no longer suitable for the existing region, the view itself calls this method and requires the parent view to re-call its onMeasure onLayout to reset its location. In particular, when the layoutparameter of the view changes and its value has not been applied to the view, this method is suitable to be called.
The postInvalidate () method is used to refresh the interface.
Public interface OnHeaderUpdateListener {/*** return the same view object in single-instance mode. * Note: The view must have the LayoutParams */public View getPinnedHeader (); public void updatePinnedHeader (int firstVisibleGroupPos );}
From the definition of the OnHeaderUpdateListener listener function, two methods are called after the listener is triggered as follows:
@Override public View getPinnedHeader() { if (mHeaderView == null) { mHeaderView = (ViewGroup) getLayoutInflater().inflate(R.layout.group, null); mHeaderView.setLayoutParams(new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT)); } return mHeaderView; }
@Override public void updatePinnedHeader(int firstVisibleGroupPos) { Group firstVisibleGroup = (Group) adapter.getGroup(firstVisibleGroupPos); TextView textView = (TextView) getPinnedHeader().findViewById(R.id.group); textView.setText(firstVisibleGroup.getTitle()); }
Next, we need to know when to trigger this listener function.
protected void refreshHeader() { if (mHeaderView == null) { return; } int firstVisiblePos = getFirstVisiblePosition(); int pos = firstVisiblePos + 1; int firstVisibleGroupPos = getPackedPositionGroup(getExpandableListPosition(firstVisiblePos)); int group = getPackedPositionGroup(getExpandableListPosition(pos)); if (group == firstVisibleGroupPos + 1) { View view = getChildAt(1); if (view.getTop() <= mHeaderHeight) { int delta = mHeaderHeight - view.getTop(); mHeaderView.layout(0, -delta, mHeaderWidth, mHeaderHeight - delta); } } else { mHeaderView.layout(0, 0, mHeaderWidth, mHeaderHeight); } if (mHeaderUpdateListener != null) { mHeaderUpdateListener.updatePinnedHeader(firstVisibleGroupPos); } }
The updatePinnerHeader method is triggered when refreshHeader () method is called.
@Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (totalItemCount > 0) { refreshHeader(); } if (mScrollListener != null) { mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount); } }
The refreshHeader is called in the onScroll method. This means that the OnHeaderUpdateListener listener will trigger when the screen is sliding, And the listener will constantly determine whether to change the column name.
It's almost one o'clock in the morning. Let's analyze it today. Continue tomorrow.
Again, this article aims to learn about the Android custom components, and explains in detail the instructor's blog "Implementation of the drop-down PinnedHeaderExpandableListView". If you have any questions, you may wish to point out it.
Source: http://blog.csdn.net/singwhatiwanna/article/details/25546871