First present
Now a lot of places have used the wheel layout wheelview, such as the choice of birthdays, style similar to the system-provided datepickerdialog, open source control is also a lot, but most are based on the requirements of the current project to draw the interface, So I wrote a wheelview that fits my project.
First, this control has the following requirements:
1, can cycle the scroll, when the upward or downward sliding to the threshold value, then the cycle begins to scroll
2, the middle piece has a piece of translucent selection area, sliding end, which piece in this selection area, choose this fast.
3. Inherit from view to draw
Then some key points are explained:
1, the whole control inherits from the view, draws in the OnDraw. The whole consists of three modules, an entire view, an entry for each block, an entry for an intermediate selection area (an additional gray area is drawn).
2, through the dynamic setting or the default settings can display the number of entries, in the top and bottom of each add a piece, meaning is to draw showcount+2 entries altogether.
3, when the top number of entries sliding more than half the height of the entry, the dynamic entry update: The bottom of the entry is deleted to join the first entry, the first entry is deleted to join the bottom of the entry.
4, the outside world can set the entry display number, font size, color, select the area hint text (in the picture that year word), the default selection, padding filler and so on.
5, in the ontouchevent, get the finger sliding gradient value, dynamically update all the current entries.
6. Dynamically calculate width in onmeasure, width of all entries, height, start y coordinate, etc.
7. Through the current entry and the coordinates of the selected item, more than half are considered to be selected and slide to the corresponding position.
The following is the Wheelview code, mainly to calculate the initial value, get the value outside set:
Package Cc.wxf.view.wheel;import Android.content.context;import Android.graphics.canvas;import Android.graphics.color;import Android.graphics.paint;import Android.util.attributeset;import Android.view.motionevent;import android.view.view;import java.util.arraylist;import java.util.List;/** * Created by CCWXF on 2016/3/31. */public class Wheelview extends View {public static final int font_color = Color.Black; public static final int font_size = 30; public static final int PADDING = 10; public static final int show_count = 3; public static final int SELECT = 0; Overall width, height, height of item, private int width; private int height; private int itemheight; The number of rows that need to be displayed private int showcount = Show_count; The current default selected location private int select = Select; Font color, size, padding private int fontcolor = Font_color; private int fontSize = Font_size; private int padding = padding; Text list private list<string> lists; The auxiliary text of the selected item, which can be an empty private String selecttip; //Each item and the selected item private list<wheelitem> wheelitems = new arraylist<wheelitem> (); Private Wheelselect wheelselect = null; Hand-clicked y-coordinate private float mtouchy; Listener Private Onwheelviewitemselectlistener listener; Public Wheelview (Context context) {super (context); } public Wheelview (context context, AttributeSet Attrs) {Super (context, attrs); } public Wheelview (context context, AttributeSet attrs, int defstyleattr) {Super (context, attrs, defstyleattr); }/** * Set the color of the font, not set the default is black * @param fontcolor * @return * * * public wheelview fontcolor (int Fontco LOR) {this.fontcolor = FontColor; return this; }/** * Sets the size of the font, not set the default is * @param fontSize * @return * * * public wheelview fontSize (int fontSize) { This.fontsize = fontSize; return this; }/** * Set the text to the top and bottom of the filter, inappropriate words by default is ten * @param padding * @return * * * public wheelview padding (int padding) { this.padding = padding; return this; /** * Sets the copied text of the selected item without setting the * @param selecttip * @return */public Wheelview Selecttip (String selecttip ) {this.selecttip = Selecttip; return this; }/** * Sets the text list, must and must be set before the Build method * @param lists * @return */public Wheelview lists (LIST<STRING&G T Lists) {this.lists = lists; return this; }/** * Sets the number of lines displayed, default is 3 * @param showcount * @return */public Wheelview showcount (int showcount) { if (showcount% 2 = = 0) {throw new IllegalStateException ("The Showcount must be odd"); } this.showcount = Showcount; return this; }/** * Sets the index of the default selected text, does not set the default to 0 * @param SELECT * @return */public Wheelview Select (int select) { This.select = select; return this; }/** * Last called method to determine if a function is not invoked * @return */public Wheelview build () {if (lists = = null) { throw new IllegalStateException ("This method must invoke after the method [lists]"); } return this; } @Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {//Get overall width = M Easurespec.getsize (Widthmeasurespec)-Getpaddingleft ()-getpaddingright (); Get the height of each item paint Mpaint = new paint (); Mpaint.settextsize (fontSize); Paint.fontmetrics metrics = Mpaint.getfontmetrics (); ItemHeight = (int) (METRICS.BOTTOM-METRICS.TOP) + 2 * padding; Initialize each of the Wheelitem initwheelitems (width, itemheight); Initialize Wheelselect wheelselect = new Wheelselect (SHOWCOUNT/2 * itemheight, Width, itemheight, Selecttip, FontColor, FontSize, padding); Get all heights height = itemheight * showcount; Super.onmeasure (Widthmeasurespec, Measurespec.makemeasurespec (height, measurespec.exactly)); }/** * Create a display number + 2 Wheelitem * @param width * @param itemhEight */private void Initwheelitems (int width, int itemheight) {wheelitems.clear (); for (int i = 0; i < Showcount + 2; i++) {int starty = ItemHeight * (i-1); int stringindex = SELECT-SHOWCOUNT/2-1 + i; if (StringIndex < 0) {StringIndex = Lists.size () + StringIndex; } wheelitems.add (New Wheelitem (starty, Width, itemheight, FontColor, FontSize, Lists.get (StringIndex))); }} @Override public boolean ontouchevent (Motionevent event) {switch (event.getaction ()) {CA Se MotionEvent.ACTION_DOWN:mTouchY = event.gety (); return true; Case MotionEvent.ACTION_MOVE:float dy = event.gety ()-mtouchy; Mtouchy = Event.gety (); Handlemove (DY); Break Case MotionEvent.ACTION_UP:handleUp (); Break } return Super.onTouchEvent (event); }/** * Handle move operation * @param dy */private void Handlemove (float dy) {//adjust coordinates for (Wheelitem ite M:wheelitems) {item.adjust (dy); } invalidate (); adjusting adjust (); }/** * Handle lift operation */private void Handleup () {int index =-1; Get the one that should be selected for (int i = 0; i < wheelitems.size (); i++) {Wheelitem item = wheelitems.get (i); If Starty is above the midpoint of SelectItem, the item is selected as the option if (Item.getstarty () > Wheelselect.getstarty () && item.getst Arty () < (Wheelselect.getstarty () + ITEMHEIGHT/2)) {index = i; Break }//If Starty is below the midpoint of SelectItem, the previous item is selected as the selection if (Item.getstarty () >= (Wheelselect.getstarty () + Itemhei GHT/2) && Item.getstarty () < (Wheelselect.getstarty () + itemheight) {index = i-1; Break }}//If not found or other factors, return directly toreturn if (index = =-1) {return; }//Get offset of the displacement float dy = wheelselect.getstarty ()-Wheelitems.get (index). Getstarty (); Adjust coordinates for (Wheelitem item:wheelitems) {item.adjust (dy); } invalidate (); adjusting adjust (); Set the selection int stringindex = Lists.indexof (Wheelitems.get (index). GetText ()); if (stringindex! =-1) {select = StringIndex; if (listener! = null) {listener.onitemselect (select); }}}/** * Adjust item move and loop Show */private void adjust () {///if swipe down above half item height, adjust container if (whe Elitems.get (0). Getstarty () >=-ITEMHEIGHT/2) {//Remove last item reuse Wheelitem item = Wheelitems.remov E (Wheelitems.size ()-1); Sets the starting point Y coordinate item.setstarty (wheelitems.get (0). Getstarty ()-itemheight); Get the text in the container index int index = lists.indexof (wheelitems.get (0). GetText ()); IF (Index = =-1) {return; } index-= 1; if (Index < 0) {index = lists.size () + index; }//Set Text Item.settext (Lists.get (index)); Added to the beginning Wheelitems.add (0, item); Invalidate (); Return }//If the top slide is above the height of the half item, adjust the container if (wheelitems.get (0). Getstarty () <= (-ITEMHEIGHT/2-itemheight)) { Remove the first item reuse Wheelitem item = wheelitems.remove (0); Sets the starting point Y coordinate Item.setstarty (Wheelitems.get (Wheelitems.size ()-1). Getstarty () + itemheight); Get the text in the container index int index = LISTS.INDEXOF (Wheelitems.get (Wheelitems.size ()-1). GetText ()); if (index = =-1) {return; Index + = 1; if (index >= lists.size ()) {index = 0; }//Set Text Item.settext (Lists.get (index)); Add to Last Face Wheelitems.add (item); Invalidate (); Return }}/** * Gets the current selection */public int getselectitem () {return select; } @Override protected void OnDraw (canvas canvas) {//Draw each item for the item for (Wheelitem Item:wheelitems) { Item.ondraw (canvas); }//Draw Shadow if (wheelselect! = null) {Wheelselect.ondraw (canvas); }}/** * Set listener * @param listener * @return * */Public Wheelview Listener (onwheelviewitemselectlis Tener listener) {This.listener = listener; return this; } public interface onwheelviewitemselectlistener{void onitemselect (int index); }}
Then each entry class is drawn according to the current coordinates, changing the coordinates according to the gradient values:
Package Cc.wxf.view.wheel;import Android.graphics.canvas;import Android.graphics.paint;import android.graphics.rectf;/** * Created by CCWXF on 2016/3/31. */public class Wheelitem {//start y coordinate, width, height private float starty; private int width; private int height; Four point coordinates private RECTF rect = new RECTF (); Font size, color private int fontcolor; private int fontSize; private String text; Private Paint Mpaint = new paint (Paint.anti_alias_flag); Public Wheelitem (float starty, int width, int height, int fontcolor, int fontSize, String text) {This.starty = STA Rty; This.width = width; This.height = height; This.fontcolor = FontColor; This.fontsize = fontSize; This.text = text; Adjust (0); }/** * Adjust the four-point coordinate value according to the change value of y-coordinate * @param dy */public void adjust (float dy) {starty + = dy; Rect.left = 0; Rect.top = Starty; Rect.right = width; Rect.bottom = starty + height; } publiC Float Getstarty () {return starty; }/** * Set the y-coordinate property directly, adjust the four-point coordinate property * @param starty */public void Setstarty (float starty) {this.starty = Starty; Rect.left = 0; Rect.top = Starty; Rect.right = width; Rect.bottom = starty + height; The public void SetText (String text) {this.text = text; } public String GetText () {return text; } public void OnDraw (Canvas mcanvas) {//Set pen property mpaint.settextsize (FontSize); Mpaint.setcolor (FontColor); Gets the width of the font int textWidth = (int) mpaint.measuretext (text); The drawing starting point of the DrawText is the lower left corner, the y-axis starting point is baseline paint.fontmetrics metrics = Mpaint.getfontmetrics (); int baseLine = (int) (Rect.centery () + (metrics.bottom-metrics.top)/2-metrics.bottom); Center Draw Mcanvas.drawtext (text, Rect.centerx ()-TEXTWIDTH/2, BaseLine, Mpaint); }}
The last option is to draw an extra gray area in the middle area:
Package Cc.wxf.view.wheel;import Android.graphics.canvas;import Android.graphics.color;import Android.graphics.paint;import android.graphics.rect;/** * Created by CCWXF on 2016/4/1. */public class Wheelselect {//black box background color public static final int color_background = Color.parsecolor ("#77777777"); The y-coordinate of the black box starts, width, height, private int starty; private int width; private int height; Four point coordinate private rect rect = new rect (); Need to select the text color, size, padding private String selecttext; private int fontcolor; private int fontSize; private int padding; Private Paint Mpaint = new paint (Paint.anti_alias_flag); Public wheelselect (int starty, int width, int height, String selecttext, int fontcolor, int fontSize, int padding) { This.starty = Starty; This.width = width; This.height = height; This.selecttext = SelectText; This.fontcolor = FontColor; This.fontsize = fontSize; this.padding = padding; Rect.left = 0; Rect.top =Starty; Rect.right = width; Rect.bottom = starty + height; } public int Getstarty () {return starty; } public void Setstarty (int starty) {this.starty = Starty; } public void OnDraw (Canvas mcanvas) {//Draw background mpaint.setstyle (Paint.Style.FILL); Mpaint.setcolor (Color_background); Mcanvas.drawrect (rect, mpaint); Draw Reminder Text if (SelectText! = null) {//Set pen property mpaint.settextsize (FontSize); Mpaint.setcolor (FontColor); Gets the width of the font int textWidth = (int) mpaint.measuretext (selecttext); The drawing starting point of the DrawText is the lower left corner, the y-axis starting point is baseline paint.fontmetrics metrics = Mpaint.getfontmetrics (); int baseLine = (int) (Rect.centery () + (metrics.bottom-metrics.top)/2-metrics.bottom); Draw text on the right Mcanvas.drawtext (SelectText, Rect.right-padding-textwidth, BaseLine, Mpaint); } }}
The source code is three files, very simple, the comments are very detailed, followed by the use of files:
Final Wheelview Wheelview = (wheelview) Findviewbyid (R.id.wheelview); Final list<string> lists = new arraylist<> (); for (int i = 0; i <; i++) { lists.add ("Test:" + i); } Wheelview.lists (lists). FontSize (+). Showcount (5). Selecttip ("Year"). Select (0). Listener (New Wheelview.onwheelviewitemselectlistener () { @Override public void onitemselect (int index) { log.d ("CC", "Current Select:" + wheelview.getselectitem () + "index:" + index + ", result=" + lists.get (index)); } ). Build ();
This control is simple and simple, it is complex and complex, from the most basic OnDraw implementation, can be very high flexibility to customize their own needs.
Demo project is not provided, the use is very simple.
Android Custom Implementation loop wheel control Wheelview