Android UI Design < 12 > Custom view for gorgeous font size control controls Fontsliderbar

Source: Internet
Author: User
Tags gety

Reprint Please specify source:http://blog.csdn.net/llew2011/article/details/51668407

Students who know about iOS should know that there is a Uisliderbar control in iOS and that the control is used in the set text size in the iphone. One of the recent product requirements is to change some of the font size in the app, although the technical difficulty is not small but the workload is still there, the idea is to use layoutinflater.factory implementation ( If you are unfamiliar with layoutinflater.factory can read the previous written Android source series < four > from the point of view of the source of the deep understanding of the theme of Layoutinflater.factory switch class article). The UI was designed to refer to iOS Uisliderbar, and the Android system did not provide a control that was directly compliant, so I wrote a uisliderbar-like control, and I named it Fontsliderbar, which works as follows:

Okay, let's get started. If this effect is achieved, before we begin to implement this function, we will analyze the effect of iOS uisliderbar, according to the left one of iOS can know that the control has a tick bar, there is a draggable ball on the top of the scale bar, So Fontsliderbar can do a split, the function of drawing table scale separately extracted with bar to represent, the drag of the ball with thumb to represent, the split diagram is as follows:

Based on the split diagram, let's analyze what properties and functions the thumb and bar should have.

  • Thumb function Analysis
            thumb is responsible for drawing operations on the screen, since the drawing operation, it is necessary to draw canvas instance, to get the canvas instance can be passed through the method, the next draw when drawing where, So the thumb needs the property coordinates xy (where the X coordinate of the thumb is changed and the Y coordinate is immutable); How big the thumb is when drawing the circle, when the finger is pressed and what color the finger is drawn, So the thumb needs to have radius attribute radius and represents the finger pressed and lifted color properties NormalColor and Pressedcolor. Well, after analysis, our thumb object can be built out, the code is as follows:
    public class Thumb {private static final float Minimum_target_radius = 50;private final float mtouchzone;private boolean m Ispressed;private final float my;private float mx;private paint mpaintnormal;private paint mpaintpressed;private float MR  adius;private int mcolornormal;private int mcolorpressed;public Thumb (float x, float y, int colornormal, int colorpressed, Float radius) {Mradius = Radius;mcolornormal = colornormal;mcolorpressed = Colorpressed;mpaintnormal = new Paint (); mPaint Normal.setcolor (Mcolornormal); Mpaintnormal.setantialias (true); mpaintpressed = new Paint (); Mpaintpressed.setcolor ( mcolorpressed); Mpaintpressed.setantialias (true); mtouchzone = (int) Math.max (Minimum_target_radius, RADIUS); MX = X;mY = y;} public void SetX (float x) {MX = x;} public float GetX () {return mX;} public boolean ispressed () {return mispressed;} public void Press () {mispressed = true;} public void Release () {mispressed = false;} public boolean Isintargetzone (float x, float y) {if (Math.Abs (x-mx) <= MtoucHzone && Math.Abs (y-my) <= Mtouchzone) {return true;} return false;} public void Draw (canvas canvas) {if (mispressed) {canvas.drawcircle (MX, MY, Mradius, mpaintpressed);} else {CANVAS.DRAWCI Rcle (MX, MY, Mradius, Mpaintnormal);}} public void Destroyresources () {if (null! = Mpaintnormal) {mpaintnormal = null;} if (null! = mpaintpressed) {mpaintpressed = null;}}}
    The thumb code is simple, and it needs to be explained that a new mtouchdelegate attribute is added to the thumb that simulates the touchdelegate feature in the Android system ( There is not familiar with the view of the touchdelegate principle, please consult the source code, this is not done in detail, the use of the scene is when the radius of the circle is too small when the finger may not click, this will affect the user experience, so set the Mtouchdelete property, It represents the smallest range of finger touches.
  • Bar function Analysis
    Bar's function is to draw the scale ruler, unexpectedly is to draw the scale first and the thumb need to have XY coordinates and the canvas instance, secondly the scale how long, how many scale, the height of the scale is what, scale color is what kind of, again scale above also has a text, the text size, The color of the text needs to know, through such analysis, we can abstract out the bar object, the code is as follows:
    public class Bar {private Paint mbarpaint;private paint mtextpaint;private final float mleftx;private final float mrightx; Private final float my;private final float mpadding;private int msegments;private float mtickdistance;private final float Mtickheight;private final float mtickstarty;private final float mtickendy;public Bar (float x, float y, float width, int ti Ckcount, float tickheight, float barwidth, int barcolor,int textcolor, int textSize, int padding) {mleftx = X;MRIGHTX = X + width;my = y;mpadding = padding;msegments = Tickcount-1;mtickdistance = Width/msegments;mtickheight = TickHeight;mTi Ckstarty = My-mtickheight/2f;mtickendy = MY + mtickheight/2f;mbarpaint = new Paint (); Mbarpaint.setcolor (BarColor); MB Arpaint.setstrokewidth (BarWidth); Mbarpaint.setantialias (true); mtextpaint = new Paint (); Mtextpaint.setcolor ( TextColor); mtextpaint.settextsize (textSize); Mtextpaint.setantialias (true);} public void Draw (canvas canvas) {drawLine (canvas);d rawticks (canvas);} public float GetlEftX () {return mleftx;} public float getrightx () {return mrightx;} public float getnearesttickcoordinate (thumb thumb) {final int nearesttickindex = Getnearesttickindex (thumb); final float Nearesttickcoordinate = Mleftx + (Nearesttickindex * mtickdistance); return nearesttickcoordinate;} public int getnearesttickindex (thumb thumb) {return Getnearesttickindex (Thumb.getx ());} public int Getnearesttickindex (float x) {return (int) ((X-MLEFTX + mtickdistance/2f)/mtickdistance);} private void DrawLine (canvas canvas) {canvas.drawline (MLEFTX, My, mrightx, my, mbarpaint);} private void Drawticks (canvas canvas) {for (int i = 0; I <= msegments; i++) {final float x = i * mtickdistance + MLEFTX ; Canvas.drawline (x, Mtickstarty, X, Mtickendy, mbarpaint); String Text = 0 = = I? "Small": msegments = = I? "Big": ""; if (! Textutils.isempty (text)) {Canvas.drawtext (text, x-gettextwidth (text)/2, mtickstarty-mpadding, Mtextpaint);}}} Float gettextwidth (String text) {return mtextpaint.measuretext (text);} Public VOID Destroyresources () {if (null! = Mbarpaint) {mbarpaint = null;} if (null! = Mtextpaint) {mtextpaint = null;}}}
    Bar's method is not too complicated, I believe the children's boots are also understood, wherein the method Getnearesttickcoordinate () method is to find the x-coordinate of the nearest scale of the thumb, getnearesttickindex () Represents the subscript that finds the nearest tick of the thumb.

After analyzing bar and thumb, we begin to implement our Fontsliderbar, first fontsliderbar inherit view and implement the constructor method, and its minor rewrite View Onmeasure () method to determine the size of the Fontsliderbar. It should be noted that if the use of Fontsliderbar when the width and height of the warp_content will be a problem, so the width and height to do the minimum value, the width of the minimum is better understood, high determination as shown:

As we can clearly calculate the minimum height of the Fontsliderbar, the width can be given a minimum value directly, then we define our Fontsliderbar, the code is as follows:

public class Fontsliderbar extends View {private static final String TAG = "Sliderbar";p rivate static final int Default_ti Ck_count = 3;private static final float default_tick_height = 24;private static final float default_bar_width = 3;private  static final int default_bar_color = color.ltgray;private static final int default_text_size = 16;private static final int Default_text_color = color.ltgray;private static final int default_text_padding = 20;private static final float default_t Humb_radius = 20;private static final int default_thumb_color_normal = 0xff33b5e5;private static final int Default_thumb_c olor_pressed = 0xff33b5e5;private int mtickcount = default_tick_count;private float mtickheight = DEFAULT_TICK_HEIGHT; private float mbarwidth = default_bar_width;private int mbarcolor = default_bar_color;private float Mthumbradius = DEFAULT _thumb_radius;private int mthumbcolornormal = default_thumb_color_normal;private int mthumbcolorpressed = DEFAULT_ thumb_color_pressed;private int Mtextsize = default_text_size;private int mtextcolor = default_text_color;private int mtextpadding = DEFAULT_TEXT_PADDING; private int mdefaultwidth = 500;private int mcurrentindex = 0;private Boolean manimation = True;private Thumb Mthumb;priva Te Bar mbar;private valueanimator manimator;private fontsliderbar.onsliderbarchangelistener mListener;public Fontsliderbar (Context context) {super (context);} Public Fontsliderbar (context context, AttributeSet Attrs) {Super (context, attrs);} Public Fontsliderbar (context context, AttributeSet attrs, int defstyle) {Super (context, attrs, Defstyle);} @Overrideprotected void onmeasure (int widthmeasurespec, int heightmeasurespec) {super.onmeasure (Widthmeasurespec, HEIGHTMEASURESPEC); int width;int height;final int measurewidthmode = Measurespec.getmode (WIDTHMEASURESPEC); final int Measureheightmode = Measurespec.getmode (HEIGHTMEASURESPEC); final int measurewidth = Measurespec.getsize ( WIDTHMEASURESPEC); final int measureheight = Measurespec.getsize (Heightmeasurespec) if (Measurewidthmode = = measurespec.at_most) {width = measurewidth;} else if (Measurewidthmode = = measurespec.exactly) {width = measurewidth;} else {width = mdefaultwidth;} if (Measureheightmode = = measurespec.at_most) {height = Math.min (getminheight (), measureheight);} else if ( Measureheightmode = = measurespec.exactly) {height = measureheight;} else {height = getminheight ();} Setmeasureddimension (width, height);} private int getminheight () {final float F = getfontheight (); return (int) (f + mtextpadding + Mthumbradius * 2);} @Overrideprotected void onsizechanged (int w, int h, int oldw, int oldh) {super.onsizechanged (W, H, OLDW, OLDH); Createbar () ; Createthumbs ();} @Overrideprotected void OnDraw (canvas canvas) {super.ondraw (canvas); Mbar.draw (canvas); Mthumb.draw (canvas);} @Overrideprotected void onvisibilitychanged (View changedview, int visibility) {super.onvisibilitychanged (Changedview , visibility); if (VISIBLE! = visibility) {stopanimation ();}} @Overrideprotected void Ondetachedfromwindow () {Destroyresources (); Super.ondetachedfromwindow ();} @Overridepublic boolean ontouchevent (Motionevent event) {if (!isenabled () | | isanimationrunning ()) {return false;} Switch (event.getaction ()) {case MotionEvent.ACTION_DOWN:return Onactiondown (Event.getx (), event.gety ()) MotionEvent.ACTION_MOVE:this.getParent (). Requestdisallowintercepttouchevent (True); return Onactionmove ( Event.getx ()); case MotionEvent.ACTION_UP:case MotionEvent.ACTION_CANCEL:this.getParent (). Requestdisallowintercepttouchevent (False), return Onactionup (Event.getx (), Event.gety ());d Efault:return true;}} Public Fontsliderbar Setonsliderbarchangelistener (Fontsliderbar.onsliderbarchangelistener listener) {MListener = Listener;return Fontsliderbar.this;} Public Fontsliderbar settickcount (int tickCount) {if (Isvalidtickcount (TickCount)) {mtickcount = TickCount;} else {LOG.E (TAG, "TickCount less than 2; Invalid TickCount. "); throw new IllegalArgumentException ("TickCount less than 2; Invalid TickCount. "); Return Fontsliderbar.this;} Public Fontsliderbar settickheight (float tickheight) {mtickheight = Tickheight;return fontsliderbar.this;} Public Fontsliderbar setbarweight (float barweight) {mbarwidth = Barweight;return fontsliderbar.this;} Public Fontsliderbar setbarcolor (int barcolor) {mbarcolor = Barcolor;return fontsliderbar.this;} Public Fontsliderbar settextsize (int textSize) {mtextsize = Textsize;return fontsliderbar.this;} Public Fontsliderbar settextcolor (int textcolor) {mtextcolor = Textcolor;return fontsliderbar.this;} Public Fontsliderbar settextpadding (int textpadding) {mtextpadding = Textpadding;return fontsliderbar.this;} Public Fontsliderbar Setthumbradius (float thumbradius) {Mthumbradius = Thumbradius;return fontsliderbar.this;} Public Fontsliderbar setthumbcolornormal (int thumbcolornormal) {mthumbcolornormal = Thumbcolornormal;return Fontsliderbar.this;} Public Fontsliderbar setthumbcolorpressed (int thumbcolorpressed) {mthumbcolorpressed = Thumbcolorpressed;return Fontsliderbar.this;} Public FontsliderbarSetthumbindex (int currentindex) {if (IndexOutOfRange (Currentindex)) {throw new IllegalArgumentException ("A Thumb Index is out of bounds. Check that it is between 0 and mTickCount-1 ");} else {if (mcurrentindex! = currentindex) {Mcurrentindex = Currentindex;if (Mlistener! = null) {mlistener.onindexchanged (t his, mcurrentindex);}}} return fontsliderbar.this;} Public Fontsliderbar withanimation (Boolean animation) {manimation = Animation;return fontsliderbar.this;} public void Applay () {createthumbs (); Createbar (); Requestlayout (); invalidate ();} public int Getcurrentindex () {return mcurrentindex;} private void Createbar () {MBar = new Bar (Getxcoordinate (), Getycoordinate (), Getbarlength (), Mtickcount, Mtickheight, MBa Rwidth,mbarcolor, Mtextcolor, Mtextsize, mtextpadding, Mthumbradius);} private void Createthumbs () {mthumb = new Thumb (Getxcoordinate (), Getycoordinate (), Mthumbcolornormal, mthumbcolorpressed, Mthumbradius);} Private float getxcoordinate () {return mthumbradius;} Private float GetycoordiNate () {return getheight ()-Mthumbradius;} Private float Getfontheight () {Paint paint = new Paint ();p aint.settextsize (mtextsize);p aint.measuretext ("large"); FontMetrics FontMetrics = Paint.getfontmetrics (); float F = Fontmetrics.descent-fontmetrics.ascent;return f;} Private float Getbarlength () {return getwidth ()-2 * getxcoordinate ();} Private Boolean indexoutofrange (int thumbindex) {return (Thumbindex < 0 | | thumbindex >= mtickcount);} Private Boolean isvalidtickcount (int tickCount) {return tickCount > 1;} Private Boolean Onactiondown (float x, float y) {if (!mthumb.ispressed () && mthumb.isintargetzone (x, y)) {Pressthu MB (mthumb);} return true;} Private Boolean Onactionmove (float x) {if (mthumb.ispressed ()) {Movethumb (mthumb, x);} return true;} Private Boolean Onactionup (float x, float y) {if (mthumb.ispressed ()) {releasethumb (mthumb);} return true;} private void pressthumb (thumb thumb) {thumb.press (); invalidate ();} private void Releasethumb (final thumb thumb) {final int tempindex = Mbar.getnearesttickindex (thumb); if (tempindex! = mcurrentindex) {mcurrentindex = Tempindex;if (null! = Mlistener) {mList Ener.onindexchanged (this, mcurrentindex);}} float start = Thumb.getx (), Float end = Mbar.getnearesttickcoordinate (thumb), if (manimation) {startanimation (thumb, Start, end);} else {thumb.setx (end); invalidate ();} Thumb.release ();} private void startanimation (final thumb thumb, float start, float end) {stopanimation (); manimator = Valueanimator.offloat (Start, end); manimator.setduration; Manimator.addupdatelistener (new Animatorupdatelistener () {@Overridepublic void Onanimationupdate (Valueanimator animation) {Final float x = (float) animation.getanimatedvalue (); Thumb.setx (x); Invalidate ();}}); Manimator.start ();} Private Boolean isanimationrunning () {if (null! = Manimator && manimator.isrunning ()) {return true;} return false;} private void Destroyresources () {stopanimation (); if (null! = MBar) {mbar.destroyresources (); mbar = null;} if (null! = Mthumb) {Mthumb.destroyresourCES (); mthumb = null;}} private void StopAnimation () {if (null! = Manimator) {manimator.cancel (); manimator = null;}}  private void Movethumb (thumb thumb, float x) {if (X < MBAR.GETLEFTX () | | x > MBAR.GETRIGHTX ()) {//Do nothing.} else {thumb.setx (x); invalidate ();}} public static interface Onsliderbarchangelistener {public void onindexchanged (Fontsliderbar rangebar, int index);}}
The default values are defined in Fontsliderbar and a series of methods for modifying properties are kicked out, and methods such as Onmeasure (), onsizechanged (), OnDraw (), ontouchevent () are rewritten fontsliderbar respectively. The Onmeasure () method determines the dimensions of the Fontsliderbar, Onsizechanged () method creates bar and thumb objects, and the Ontouchevent () method determines whether the thumb can be dragged by clicking on the finger. Finally, the Onsliderbarchangelistener interface is defined to make it easier to do callback operations when the thumb subscript changes. The use of Fontsliderbar is also simple, and can be directly chained when setting properties, as shown below:
Fontsliderbar Sliderbar = (fontsliderbar) Findviewbyid (R.id.sliderbar); Sliderbar.settickcount (6). SetTickHeight (30) . Setbarcolor (Color.magenta). SetTextColor (Color.cyan). settextpadding (Settextsize). Setthumbradius (20). Setthumbcolornormal (Color.cyan). setthumbcolorpressed (Color.green). Withanimation (False). Applay ();
Now look at the effect of the run, as shown below:


OK, the explanation about Fontsliderbar is over, thanks for watching (*^__^*) ...






Android UI Design < 12 > Custom view for gorgeous font size control controls Fontsliderbar

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.