Android Custom View-------iOS-style slide switch

Source: Internet
Author: User
Tags getcolor

Source code and test examples have been put on GitHub Https://github.com/Leaking/SlideSwitch, welcome star Welcome Fork Welcome to mention issue

Project development, there are often some user personalization settings, at this time often need a switch control, the weekend to write the custom switch control is optimized, as follows. First of all, about the idea: The button draws three layers, the bottom is the gray covering the entire view, the second is a custom color covering the entire view, which can change the transparency. The third one is white. When the white part moves, the transparency of the second layer is modified to make the color gradient in the sliding process.


Probably record the implementation process of rewriting a component.

1, defining attributes

2, the constructor in Java code gets the value of the property

3, rewrite onmeasure ()

4, rewrite OnDraw ()

5, if necessary, rewrite Ontouch monitor

6, in the layout file of your project, define a namespace, use the properties


1, defining attributes

Create a new project, name Slieswitch, and create a new property file Slideswitch\res\values\attrs.xml

<?xml version= "1.0" encoding= "Utf-8"?><resources> <declare-styleable    name= "Slideswitch" >        <attr name= "themecolor" format= "color"/> <attr name=        "IsOpen" format= "boolean"/>        <attr Name= "Shape" >            <enum name= "rect" value= "1"/>            <enum name= "Circle" value= "2"/>        </attr >    </declare-styleable></resources>
It defines three properties, one is the color of the button, one is the open state of the button, one is the enumeration type, it is used to describe the shape of the button, about these properties and the use of several other types of properties, you can easily Baidu Google to the relevant knowledge, here is not a record.


2, the constructor in Java code gets the value of the property

Create a new package Com.leaking.slideswitch in Slieswitch, and then add a new file file Slieswitch.java in the package. The custom component first has to inherit the view class and then get the custom attributes in the constructor, as in the following Emma fragment:

public class Slideswitch extends View {//,,,,,,, omitted,,,,,,,,,, public Slideswitch (context context, AttributeSet attrs, int d EFSTYLEATTR) {Super (context, attrs, defstyleattr); listener = Null;paint = new Paint ();p Aint.setantialias (true); TypedArray a = context.obtainstyledattributes (attrs,r.styleable.slideswitch); color_theme = A.getcolor ( R.styleable.slideswitch_themecolor,color_theme); IsOpen = A.getboolean (R.styleable.slideswitch_isopen, false); Shape = A.getint (R.styleable.slideswitch_shape, Shape_rect); A.recycle ();} Public Slideswitch (context context, AttributeSet Attrs) {This (context, attrs, 0);} Public Slideswitch (Context context) {This (context, null);}         ,,,,,,, Omit,,,,,,,,,,}
General view has three constructors, I used to let only one parameter of the construction method call has two parameters of the construction method, and then two calls three, in the construction method with three parameters using Typearray read the custom property, and then call Typearray's Recycle () method to reclaim resources.


3, rewrite onmeasure ()

Search the Internet a little bit, soon can only how to rewrite the Onmeasure () method, but why the need to rewrite the Onmeasure () method This point, it is not good to search. This question I recorded in another article.

Android Custom View-------why rewrite onmeasure () and how to rewrite

We have done two things here in Onmeasure (), the first is to calculate the size of the view, which is its length and width, the second is to record the starting position of the white color block, and some other parameters of the draw button. It is important to note that when you call the view's invalidate () method to redraw, the system only calls the OnDraw () method, but if there is a modification to the size and content of other components (such as the SetText () of TextView), Will trigger Onmeasure (), so the positional variables computed in onmeasure () are not affected by the recall of Onmeasure (). One of the bugs that the encoding process encounters is for this reason.

4, rewrite OnDraw ()

The OnDraw () section is relatively easy, just draw three layers according to the parameters calculated in Onmeasure ().


5, if necessary, rewrite Ontouch monitor

It is also easier to modify the transparency of the second layer's color by the Down,move,up three event calculation location, and then call Invaliate to redraw the view. Start a thread in the up event and let the button slide automatically to the end.


6, in the layout file of your project, define a namespace, using properties

<linearlayout xmlns:android= "http://schemas.android.com/apk/res/android"    xmlns:tools= "http// Schemas.android.com/tools "    xmlns:slideswitch=" Http://schemas.android.com/apk/res/com.example.testlibs "    android:layout_width= "match_parent"    android:layout_height= "match_parent"    android:background= "# FFFFFFFF "    android:gravity=" center_horizontal "    android:orientation=" vertical "    android:padding=" 10dip "    tools:context=" com.example.testlibs.MainActivity ">    <com.leaking.slideswitch.slideswitch        android:id= "@+id/swit"        android:layout_width= "150dip"        android:layout_height= "60dip"        Slideswitch:isopen= "true"        slideswitch:shape= "rect"        slideswitch:themecolor= "#ffee3a00" >    </ Com.leaking.slideswitch.slideswitch></linearlayout>

It is important to note that the second line of the preceding code fragment introduces a namespace with the following format
xmlns: Random name = "Http://schemas.android.com/apk/res/the package name of your app"
Note that the last part is the app package name for the project that you use for this custom view.
Next, set the switch's listening and status settings in the Java code, as shown in the following code
public class Mainactivity extends Activity implements Slidelistener {TextView txt; Slideswitch Slide; Slideswitch slide2; @Overrideprotected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Setcontentview (r.layout.activity_main); slide = (slideswitch) Findviewbyid (r.id.swit); slide2 = (Slideswitch) Findviewbyid (R.ID.SWIT2); Slide.setstate (false); txt = (TextView) Findviewbyid (r.id.txt); Slide.setslidelistener ( this);} @Overridepublic void Open () {//TODO auto-generated method Stubtxt.settext ("is Opend");} @Overridepublic void Close () {//TODO auto-generated method Stubtxt.settext ("is close");}}





Slideswitch.java Complete Code
Complete code and test examples are on GitHub, Https://github.com/Leaking/SlideSwitch.
Package Com.leaking.slideswitch;import Android.content.context;import Android.content.res.typedarray;import Android.graphics.canvas;import Android.graphics.color;import Android.graphics.paint;import Android.graphics.Rect; Import Android.graphics.rectf;import android.os.handler;import Android.os.looper;import Android.os.Message;import Android.support.v4.view.motioneventcompat;import Android.util.attributeset;import android.view.MotionEvent; Import Android.view.view;import Com.example.slideswitch.r;public class Slideswitch extends View {public static final int Shape_rect = 1;public static final int shape_circle = 2;private static final int rim_size = 6;private static final int COL Or_theme = Color.parsecolor ("#ff00ee00");//3 Attributesprivate int color_theme;private boolean isopen;private int shape ;//Varials of drawingprivate Paint paint;private rect backrect;private rect frontrect;private int alpha;private int max_l eft;private int min_left;private int frontrect_left;private int Frontrect_left_begin = rim_size;private int eventstartx;private int eventlastx;private int DIFFX = 0;private SlideListener Listener ;p Ublic interface Slidelistener {public void open ();p ublic void Close ();} Public Slideswitch (context context, AttributeSet attrs, int defstyleattr) {Super (context, attrs, defstyleattr); listener = Null;paint = new Paint ();p Aint.setantialias (true); TypedArray a = context.obtainstyledattributes (attrs,r.styleable.slideswitch); color_theme = A.getcolor ( R.styleable.slideswitch_themecolor,color_theme); IsOpen = A.getboolean (R.styleable.slideswitch_isopen, false); Shape = A.getint (R.styleable.slideswitch_shape, Shape_rect); A.recycle ();} Public Slideswitch (context context, AttributeSet Attrs) {This (context, attrs, 0);} Public Slideswitch (Context context) {This (context, null);}} @Overrideprotected void onmeasure (int widthmeasurespec, int heightmeasurespec) {super.onmeasure (Widthmeasurespec, HEIGHTMEASURESPEC); int width = measuredimension (280, widthmeasurespec); int height = MeasuredimEnsion (HEIGHTMEASURESPEC); if (shape = = shape_circle) {if (Width < height) width = height * 2;} Setmeasureddimension (width, height); Initdrawingval ();} public void Initdrawingval () {int width = getmeasuredwidth (); int height = getmeasuredheight (); backrect = new Rect (0, 0, wid th, height); min_left = rim_size;if (Shape = = shape_rect) Max_left = Width/2;elsemax_left = width-(height-2 * rim_size )-Rim_size;if (isOpen) {frontrect_left = Max_left;alpha = 255;} else {frontrect_left = Rim_size;alpha = 0;} Frontrect_left_begin = Frontrect_left;} public int measuredimension (int defaultsize, int measurespec) {int Result;int specmode = Measurespec.getmode (measureSpec  int specsize = Measurespec.getsize (Measurespec), if (Specmode = = measurespec.exactly) {result = Specsize;} else {result = DefaultSize; Unspecifiedif (Specmode = = measurespec.at_most) {result = Math.min (result, specsize);}} return result;} @Overrideprotected void OnDraw (canvas canvas) {if (shape = = shape_rect) {Paint.setcolor (ColoR.gray); Canvas.drawrect (backrect, paint);p Aint.setcolor (color_theme);p Aint.setalpha (Alpha); Canvas.drawrect ( Backrect, paint); frontrect = new Rect (Frontrect_left, Rim_size, frontrect_left+ getmeasuredwidth ()/2-rim_size, GetMeas Uredheight ()-rim_size);p Aint.setcolor (Color.White); Canvas.drawrect (frontrect, paint);} else {//draw round int radius;radius = Backrect.height ()/2-rim_size;paint.setcolor (Color.gray); Canvas.drawroundrect (new RECTF (backrect), radius, radius, paint);p Aint.setcolor (color_theme);p Aint.setalpha (Alpha); Canvas.drawroundrect ( New RECTF (Backrect), radius, radius, paint) Frontrect = new Rect (Frontrect_left, Rim_size, frontrect_left+ Backrect.height ()-2 * rim_size, Backrect.height ()-rim_size);p Aint.setcolor (Color.White); Canvas.drawroundrect (new RECTF (frontrect), radius, radius, paint);}} @Overridepublic boolean ontouchevent (Motionevent event) {int action = motioneventcompat.getactionmasked (event); switch (action) {Case MotionEvent.ACTION_DOWN:eventStartX = (int) Event.getrawX (); Break;case MotionEvent.ACTION_MOVE:eventLastX = (int) event.getrawx ();d iffx = Eventlastx-eventstartx;int tempx = di FfX + frontrect_left_begin;tempx = (tempx > max_left? max_left:tempx); tempx = (Tempx < min_left? min_left:temp X); if (tempx >= min_left && tempx <= max_left) {frontrect_left = Tempx;alpha = (int) (255 * (float) tempx/ (float) max_left); Invalidateview ();} Break;case MotionEvent.ACTION_UP:int Wholex = (int) (EVENT.GETRAWX ()-eventstartx); frontrect_left_begin = Frontrect_ Left;boolean toright;toright = (Frontrect_left_begin > MAX_LEFT/2 true:false); if (Math.Abs (WholeX) < 3) {ToRig HT =!toright;} Movetodest (toright); break;default:break;} return true;} /** * Draw again */private void Invalidateview () {if (looper.getmainlooper () = = Looper.mylooper ()) {invalidate ();} else {P Ostinvalidate ();}} public void Setslidelistener (Slidelistener listener) {This.listener = listener;} public void Movetodest (final Boolean toright) {final Handler Handler =New Handler () {@Overridepublic void Handlemessage (Message msg) {if (msg.what = = 1) {Listener.open ();} else {Listener.close ();}}}; New Thread (New Runnable () {@Overridepublic void run () {if (toright) {while (Frontrect_left <= max_left) {alpha = (int) (255 * (float) frontrect_left/(float) max_left); Invalidateview (); Frontrect_left + = 3;try {thread.sleep (3);} catch (Inte Rruptedexception e) {e.printstacktrace ();}} Alpha = 255;frontrect_left = Max_left;isopen = true;if (listener! = null) handler.sendemptymessage (1); Frontrect_left_ begin = Max_left;} else {while (Frontrect_left >= min_left) {alpha = (int) (255 * (float) frontrect_left/(float) max_left); Invalidatevie W (); Frontrect_left-= 3;try {thread.sleep (3);} catch (Interruptedexception e) {e.printstacktrace ();}} Alpha = 0;frontrect_left = Min_left;isopen = false;if (listener! = null) handler.sendemptymessage (0); Frontrect_left_ begin = Min_left;}}). Start ();} public void SetState (Boolean isOpen) {This.isopen = Isopen;initdrawingval (); invalIdateview (); if (listener! = null) if (IsOpen = = True) {Listener.open ();} Else{listener.close ();}} public void Setshapetype (int shapetype) {this.shape = ShapeType;}}





Finally, by the way, how to csdn in the blog gif pictures: Can not directly upload pictures, but first to send Pictures csdn album, and then copy the picture in the album Link

Android Custom View-------iOS-style slide switch

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.