⚠️ Note: This article was written on 2016-08-02
I’m sure you’ve seen alphabetic interfaces in many apps, such as this open source control I recently saw:
WaveSideBar
Isn’t that cool? !!!!!!!!! If it is added to the contact list interface, the user experience is greatly improved.
So this index control how to do it, in the final analysis is to customize a view, because of their own ability reasons I can not make such an effect, of course, you can go to study this kind of open source index control source.
This is all I can do right now:
It’s easy, but it’s good for beginners to learn something. Let’s start by writing an alphabetically indexed control called SimpleSideBar
Prepare some knowledge
Here is a series of posts by blogger Guolin
Blog.csdn.net/guolin_blog…
Blog.csdn.net/guolin_blog…
Blog.csdn.net/jdsjlzx/art…
The first step is to create a class SimpleSideBar that inherits the View
public class SimpleSideBar extends View { public SimpleSideBar(Context context) { super(context); } public SimpleSideBar(Context context, AttributeSet attrs) { super(context, attrs); } public SimpleSideBar(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); }}Copy the code
The second step is to declare the required variables
/ / reference letter array private String [] alphabet = {" A ", "B", "C", "D", "E", "F", "G", "H" and "I" and "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" }; / / the index to the currently selected index letters private int currentChoosenAlphabetIndex = 1; Private Paint mPaint=new Paint(); Private int alphabetTextSize=20;Copy the code
Third, rewrite the onDraw function
This function is a draw function that renders the control content
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); Int viewHeight=getHeight(); Int viewWidth=getWidth(); / / control height divided by the number of reference letter for the height of each index letters int heightPerAlphabet = viewHeight/alphabet. Length; // Loop through each index letter and draw out for (int I =0; i<alphabet.length; I++){// set the pen Color, brush text thickness and size, and set the anti-aliasing mPaint. SetColor (color.black); mPaint.setTypeface(Typeface.DEFAULT_BOLD); mPaint.setTextSize(alphabetTextSize); mPaint.setAntiAlias(true); / / if the currently selected index letters subscript subscript same and circulation to the index of the letter if (currentChoosenAlphabetIndex = = I) {/ / set the brush Color, draw the text size and bold mPaint. SetColor (Color. YELLOW); mPaint.setTextSize(alphabetTextSize); mPaint.setFakeBoldText(true); Float xPos=viewWidth/2-mPaint. MeasureText (Alphabet [I])/2; float xPos=viewWidth/2-mPaint. Float yPos=heightPerAlphabet* I +heightPerAlphabet; float yPos=heightPerAlphabet* I +heightPerAlphabet; DrawText (alphabet[I],xPos,yPos,mPaint); // Reset the brush in preparation for drawing the next index letter mPaint. Reset (); }}Copy the code
Here, we add the control to layout and it can be displayed, but we do not touch the index letters to make the ListView/RecyclerView scroll to the corresponding position.
To do this, we need to override the dispatchTouchEvent function to handle control touch events and provide an interface to scroll the list to the appropriate location.
Let’s go ahead and implement it.
Step four, provide an interface
Start by defining an interface
public interface OnLetterTouchedChangeListener{
void onTouchedLetterChange(String letterTouched);
}
Copy the code
We then declare an interface variable that provides the set method
OnLetterTouchedChangeListener onLetterTouchedChangeListener;
public void setOnLetterTouchedChangeListener(OnLetterTouchedChangeListener onLetterTouchedChangeListener) {
this.onLetterTouchedChangeListener = onLetterTouchedChangeListener;
}
Copy the code
Fifth, rewrite the dispatchTouchEvent function
This function is a control touch event dispenser. When the return value is true, it does not proceed to the next level of processing.
@override public Boolean dispatchTouchEvent(MotionEvent) {int action = event.getAction(); Float touchYPos=event. GetY (); float touchYPos=event. // Divide the control height by the number of index letters to get the height of each index letter. Int currentTouchIndex= (int) (touchYPos/getHeight()*alphabet.length); ACTION_DOWN: case MotionEvent.ACTION_MOVE: Case MotionEvent. // Set the background color setBackgroundResource(r.color.grey_600); / / set the current selected reference letter for the value of the currently selected value currentChoosenAlphabetIndex = currentTouchIndex; / / if interface exists and the index values under legal, implement the interface method, was introduced into the current touch the index of the letters, for external call accepts the if (onLetterTouchedChangeListener! =null&¤tTouchIndex<alphabet.length&¤tTouchIndex>-1){ onLetterTouchedChangeListener.onTouchedLetterChange(alphabet[currentTouchIndex]); } // redraw the control, i.e. re-execute the onDraw function invalidate(); break; case MotionEvent.ACTION_UP: setBackgroundResource(R.color.grey_50); / / when stop touch controls, set for the currently selected index values under the letter - 1 currentChoosenAlphabetIndex = 1; invalidate(); break; default:break; } // Return true to indicate that the touch event is processed and not distributed. }Copy the code
Step 6, use a custom SimpleSideBar control
activity_main.xml
<? The XML version = "1.0" encoding = "utf-8"? > <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/root" android:orientation="horizontal" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:layout_weight="1" android:layout_width="0dp" android:layout_height="match_parent"> <android.support.v7.widget.RecyclerView android:id="@+id/recycler_view" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout> <me.pwcong.simplesidebar.view.SimpleSideBar android:id="@+id/sideBar" android:layout_width="30dp" android:layout_height="wrap_content" /> </LinearLayout>Copy the code
MainActivity.java
. sideBar= (SimpleSideBar) findViewById(R.id.sideBar); / / use the previously defined interface sideBar. Here setOnLetterTouchedChangeListener (new SimpleSideBar. OnLetterTouchedChangeListener () {@ Override Public void onTouchedLetterChange(String letterTouched) {// get the index letterTouched and the index letter of the corresponding item. Perform list rolling method int pos = simpleAdapter. GetLetterPosition (letterTouched); if(pos! =-1){ recyclerView.scrollToPosition(pos); }}});Copy the code
At this point our simple indexed alphabetic control is complete, and the Demo of SimpleSideBar can be downloaded here
Github.com/pwcong/Simp…