Android contact pinnedheaderlistview

Source: Internet
Author: User

The listview In the android contact is unique, but the source code is relatively copied. It is not easy to extract it from the source code when we want to use it, and it is prone to errors, in the past few days, I have extracted it and written it as a simple example. I will give myself a memo, but I will share it with you. Well, let's take a look:

The first is the encapsulated pinnedheaderlistview with a header:

public class PinnedHeaderListView extends ListView {public interface PinnedHeaderAdapter {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;int getPinnedHeaderState(int position);void configurePinnedHeader(View header, int position, int alpha);}private static final int MAX_ALPHA = 255;private PinnedHeaderAdapter mAdapter;private View mHeaderView;private boolean mHeaderViewVisible;private int mHeaderViewWidth;private int mHeaderViewHeight;public PinnedHeaderListView(Context context) {super(context);}public PinnedHeaderListView(Context context, AttributeSet attrs) {super(context, attrs);}public PinnedHeaderListView(Context context, AttributeSet attrs,int defStyle) {super(context, attrs, defStyle);}    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {        super.onLayout(changed, left, top, right, bottom);        if (mHeaderView != null) {            mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight);            configureHeaderView(getFirstVisiblePosition());        }    }    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        if (mHeaderView != null) {            measureChild(mHeaderView, widthMeasureSpec, heightMeasureSpec);            mHeaderViewWidth = mHeaderView.getMeasuredWidth();            mHeaderViewHeight = mHeaderView.getMeasuredHeight();        }    }public void setPinnedHeaderView(View view) {mHeaderView = view;if (mHeaderView != null) {setFadingEdgeLength(0);}requestLayout();}    public void setAdapter(ListAdapter adapter) {        super.setAdapter(adapter);        mAdapter = (PinnedHeaderAdapter)adapter;    }public void configureHeaderView(int position) {if (mHeaderView == null) {return;}int state = mAdapter.getPinnedHeaderState(position);switch (state) {case PinnedHeaderAdapter.PINNED_HEADER_GONE: {mHeaderViewVisible = false;break;}case PinnedHeaderAdapter.PINNED_HEADER_VISIBLE: {mAdapter.configurePinnedHeader(mHeaderView, position, MAX_ALPHA);if (mHeaderView.getTop() != 0) {mHeaderView.layout(0, 0, mHeaderViewWidth, mHeaderViewHeight);}mHeaderViewVisible = true;break;}case PinnedHeaderAdapter.PINNED_HEADER_PUSHED_UP: {View firstView = getChildAt(0);int bottom = firstView.getBottom();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.configurePinnedHeader(mHeaderView, position, alpha);if (mHeaderView.getTop() != y) {mHeaderView.layout(0, y, mHeaderViewWidth, mHeaderViewHeight+ y);}mHeaderViewVisible = true;break;}}}    protected void dispatchDraw(Canvas canvas) {        super.dispatchDraw(canvas);        if (mHeaderViewVisible) {            drawChild(canvas, mHeaderView, getDrawingTime());        }    }}

Then there is the quick navigation bladeview (Blade ):

public class BladeView extends View {private OnItemClickListener mOnItemClickListener;String[] b = { "#", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K","L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X","Y", "Z" };int choose = -1;Paint paint = new Paint();boolean showBkg = false;private PopupWindow mPopupWindow;private TextView mPopupText;private Handler handler = new Handler();public BladeView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}public BladeView(Context context, AttributeSet attrs) {super(context, attrs);}public BladeView(Context context) {super(context);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);if (showBkg) {canvas.drawColor(Color.parseColor("#00000000"));}int height = getHeight();int width = getWidth();int singleHeight = height / b.length;for (int i = 0; i < b.length; i++) {paint.setColor(Color.BLACK);paint.setTypeface(Typeface.DEFAULT_BOLD);paint.setFakeBoldText(true);paint.setAntiAlias(true);if (i == choose) {paint.setColor(Color.parseColor("#3399ff"));}float xPos = width / 2 - paint.measureText(b[i]) / 2;float yPos = singleHeight * i + singleHeight;canvas.drawText(b[i], xPos, yPos, paint);paint.reset();}}@Overridepublic boolean dispatchTouchEvent(MotionEvent event) {final int action = event.getAction();final float y = event.getY();final int oldChoose = choose;final int c = (int) (y / getHeight() * b.length);switch (action) {case MotionEvent.ACTION_DOWN:showBkg = true;if (oldChoose != c) {if (c > 0 && c < b.length) {performItemClicked(c);choose = c;invalidate();}}break;case MotionEvent.ACTION_MOVE:if (oldChoose != c) {if (c > 0 && c < b.length) {performItemClicked(c);choose = c;invalidate();}}break;case MotionEvent.ACTION_UP:showBkg = false;choose = -1;dismissPopup();invalidate();break;}return true;}private void showPopup(int item) {if (mPopupWindow == null) {handler.removeCallbacks(dismissRunnable);mPopupText = new TextView(getContext());mPopupText.setBackgroundColor(Color.GRAY);mPopupText.setTextColor(Color.CYAN);mPopupText.setTextSize(50);mPopupText.setGravity(Gravity.CENTER_HORIZONTAL| Gravity.CENTER_VERTICAL);mPopupWindow = new PopupWindow(mPopupText, 100, 100);}String text = "";if (item == 0) {text = "#";} else {text = Character.toString((char) ('A' + item - 1));}mPopupText.setText(text);if (mPopupWindow.isShowing()) {mPopupWindow.update();} else {mPopupWindow.showAtLocation(getRootView(),Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL, 0, 0);}}private void dismissPopup() {handler.postDelayed(dismissRunnable, 800);}Runnable dismissRunnable = new Runnable() {@Overridepublic void run() {// TODO Auto-generated method stubif (mPopupWindow != null) {mPopupWindow.dismiss();}}};public boolean onTouchEvent(MotionEvent event) {return super.onTouchEvent(event);}public void setOnItemClickListener(OnItemClickListener listener) {mOnItemClickListener = listener;}private void performItemClicked(int item) {if (mOnItemClickListener != null) {mOnItemClickListener.onItemClick(b[item]);showPopup(item);}}public interface OnItemClickListener {void onItemClick(String s);}}


The next step is to use it. Declare activity_main.xml in the layout file:

<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.view.PinnedHeaderListView        android:id="@+id/friends_display"        android:layout_width="fill_parent"        android:layout_height="fill_parent"        android:cacheColorHint="#00000000"        android:divider="@null"        android:footerDividersEnabled="false"        android:headerDividersEnabled="false" />    <com.way.view.BladeView        android:id="@+id/friends_myletterlistview"        android:layout_width="30dip"        android:layout_height="fill_parent"        android:layout_alignParentRight="true"        android:background="#00000000" /></RelativeLayout>

Then there is an independent Adapter. This time I didn't put it in mainactivity as an internal class:

Public class friendsadapter extends baseadapter implements sectionindexer, pinnedheaderadapter, onscrolllistener {private int mlocationposition =-1; private string [] mdatas; // initial set Private list <string> mfriendssections; private list <integer> mfriendspositions; private layoutinflater Inflater; Public friendsadapter (context, string [] datas, list <string> friendssections, list <integer> friendsposition S) {// todo auto-generated constructor stubinflater = layoutinflater. from (context); mdatas = datas; mfriendssections = friendssections; mfriendspositions = friendspositions;} @ overridepublic int getcount () {// todo auto-generated method stubreturn mdatas. length ;}@ overridepublic object getitem (INT position) {// todo auto-generated method stubreturn mdatas [position] ;}@ overridepublic long getitemid (INT P Osition) {// todo auto-generated method stubreturn position;} @ overridepublic view getview (INT position, view convertview, viewgroup parent) {// todo auto-generated method stubint section = getsectionforposition (position); If (convertview = NULL) {convertview = Inflater. inflate (R. layout. listview_item, null);} linearlayout mheaderparent = (linearlayout) convertview. findviewbyid (R. id. friends_item_head Er_parent); textview mheadertext = (textview) convertview. findviewbyid (R. id. friends_item_header_text); If (getpositionforsection (section) = position) {mheaderparent. setvisibility (view. visible); mheadertext. settext (mfriendssections. get (section);} else {mheaderparent. setvisibility (view. gone);} textview = (textview) convertview. findviewbyid (R. id. friends_item); textview. settext (mdatas [position]); Return convertview;} @ overridepublic void onscrollstatechanged (abslistview view, int scrollstate) {// todo auto-generated method stub} @ overridepublic void onscroll (abslistview view, int success, int visibleitemcount, int totalitemcount) {// todo auto-generated method stubif (view instanceof pinnedheaderlistview) {(pinnedheaderlistview) view ). configureheaderview (firstvisibleitem) ;}}@ overri Depublic int getpinnedheaderstate (INT position) {int realposition = position; if (realposition <0 | (mlocationposition! =-1 & mlocationposition = realposition) {return pinned_header_gone;} mlocationposition =-1; int section = getsectionforposition (realposition); int nextsectionposition = getpositionforsection (section + 1 ); if (nextsectionposition! =-1 & realposition = nextsectionposition-1) {return pinned_header_pushed_up;} return pinned_header_visible;} @ overridepublic void configurepinnedheader (view header, int position, int alpha) {// todo auto-generated method stubint realposition = position; int section = getsectionforposition (realposition); String title = (string) getsections () [section]; (textview) header. findviewbyid (R. id. friends_list _ Header_text )). settext (title) ;}@ overridepublic object [] getsections () {// todo auto-generated method stubreturn mfriendssections. toarray () ;}@ overridepublic int getpositionforsection (INT section) {If (section <0 | section> = mfriendssections. size () {return-1;} return mfriendspositions. get (section) ;}@ overridepublic int getsectionforposition (INT position) {// todo auto-generated method stubif (Pos Ition <0 | position> = getcount () {return-1;} int Index = arrays. binarysearch (mfriendspositions. toarray (), position); Return index> = 0? Index:-index-2 ;}}

Finally, it is processed in mainactivity:

Public class mainactivity extends activity {Private Static final string format = "^ [A-Z, A-Z]. * $ "; private pinnedheaderlistview mlistview; private bladeview mletter; private friendsadapter madapter; private string [] datas; // The initial set Private list <string> msections; // store the data private Map <string, list <string> MMAP according to the initial character; // The initial position set Private list <integer> mpositions; // Private Map <string, integer> mindexer; @ ove Rrideprotected void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. activity_main); initdata (); initview ();} private void initdata () {datas = getresources (). getstringarray (R. array. countries); msections = new arraylist <string> (); MMAP = new hashmap <string, list <string> (); mpositions = new arraylist <integer> (); mindexer = new hashmap <string, integer> (); (Int I = 0; I <datas. length; I ++) {string firstname = datas [I]. substring (0, 1); If (firstname. matches (Format) {If (msections. contains (firstname) {MMAP. get (firstname ). add (datas [I]);} else {msections. add (firstname); List <string> List = new arraylist <string> (); list. add (datas [I]); MMAP. put (firstname, list) ;}} else {If (msections. contains ("#") {MMAP. get ("#"). add (datas [I]);} else {msections. add ("#"); lis T <string> List = new arraylist <string> (); list. add (datas [I]); MMAP. put ("#", list) ;}} collections. sort (msections); int position = 0; For (INT I = 0; I <msections. size (); I ++) {mindexer. put (msections. get (I), position); // saved to map. The key is the first letter string, and the value is the first letter in listview. add (position); // position of the first character in the listview, Which is saved to position + = MMAP in the list. get (msections. get (I )). size (); // calculate the position of the next initial in listview} private void initview () {// Todo auto-generated method stubmlistview = (pinnedheaderlistview) findviewbyid (R. id. friends_display); mletter = (bladeview) findviewbyid (R. id. friends_myletterlistview); mletter. setonitemclicklistener (New onitemclicklistener () {@ overridepublic void onitemclick (string s) {If (mindexer. get (s )! = NULL) {mlistview. setselection (mindexer. get (s) ;}}}); madapter = new friendsadapter (this, datas, msections, mpositions); mlistview. setadapter (madapter); mlistview. setonscrolllistener (madapter); mlistview. setpinnedheaderview (layoutinflater. from (this ). inflate (R. layout. listview_head, mlistview, false ));}}

There is a data arrays. XML, I don't post it out, interested friends can look at the source code: http://download.csdn.net/detail/weidi1989/5576125

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.