Today to talk about customizing a single control, take the switch button to say, I believe you see a lot of such a, first look at the effect:
We can see a very common switch button, then analyze and analyze.
First of all:
This is composed of two pictures:
① a background picture with open and closed
② a sliding button for control on and off
First step:
Write a class to inherit view and rewrite several methods:
The first is the constructor, the function that overrides a parameter and the two-parameter functions is enough, because a function of two parameters can use a custom property
The second is to control the size of the control –>protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {}
the third method for drawing the control –>protected void OnDraw (Canvas Canvas) {}
Step Two:
Loads the user-specified two pictures, using custom attributes to load, creating a new Attrs.xml in the values directory, specifying a custom property name and a custom attribute's field and value type (that is, background and slider charts) in the XML file:
<?xml version= "1.0" encoding= "Utf-8"?>
<resources>
<declare-styleable name= "Switchview_ Attrs ">
<attr name=" background "format=" reference "></attr> <attr name=" slide "format="
Reference "></attr>
</declare-styleable>
</resources>
The meaning of each field I'm not going to talk about it here, I don't understand. The previous several "Android development notes of the custom Combination control" has been said, write well just in the constructor loaded in
Public SwitchView (context, AttributeSet attrs) {
Super (context, attrs);
Get the custom attribute
TypedArray ta = context.obtainstyledattributes (attrs, r.styleable.switchview_attrs);
Get the value of the custom field
drawable Switchbackground = ta.getdrawable (r.styleable.switchview_attrs_background);
drawable switchview_slide = ta.getdrawable (r.styleable.switchview_attrs_slide);
Set the value to the corresponding component
Backgroundbitmap = Convertdrawable2bitmapsimple (switchbackground);
Switchslide = Convertdrawable2bitmapsimple (switchview_slide);
}
However, it is to be noted that:
Because the Drawable object is taken from the custom attribute, and we want a bitmap object, we first have to convert the Drawable object to bitmap object, there are many ways to turn, and here is the simplest way to introduce With the help of the Bitmapdrawable class:
Convert drawable to Bitmap public
Bitmap convertdrawable2bitmapsimple (drawable drawable) {
bitmapdrawable bd= ( bitmapdrawable) drawable;
return Bd.getbitmap ();
}
Step Three:
Onmeasure method to control the size of the control, we can see that the switch button size is the same size as the background, only need to set the size of the background:
Controls the size of the control
@Override
protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {
if ( Backgroundbitmap!= null) {
//control size is set to the size of the background
setmeasureddimension (Backgroundbitmap.getwidth (), Backgroundbitmap.getheight ());
} else {
super.onmeasure (Widthmeasurespec, Heightmeasurespec);
}
}
Fourth Step:
Since this switch button needs to be clicked or moved to control the control on and off, so you need to implement the Ontouchevent method, of course, there should be three events will trigger: Press, move and lift, each click, move or lift all need to redraw, Let's first analyze the status of the slide block (there should be four states). The default state is null at the beginning:
1. Click on the time
2. When moving
3. Lift up the time
4. Empty time (that is, when nothing is done)
First analysis of the next click when the situation:
① move the slider to the right when the coordinates pressed or moved are greater than half the width of the slider
② the slider does not move when the coordinates pressed or moved are less than half the width of the slider
Note: prevents the slider from moving to the outside of the background, the largest of which is the right side of the slider and the right side of the background (that is, the maximum left background width-slider width)
Take a look at the move when the situation should be the same as when clicked.
Then analyze the situation when lifting:
① move the slider to the right if the switch state is turned on
② move the slider to the left if the switch state is off
How do you judge when it's turned on and off?
① is set to open when the coordinates raised are greater than half the background width
② is set to closed when the coordinates of the lifting are less than half the background width coordinates
When you analyze the empty space, you can see that it is the same as when you lift it.
Fifth Step:
Draw the background and slider in the OnDraw method. Just analyzed the Ontouchevent method, this time is the same, the slider's four states are processed separately, the previous Ontouchevent method in the slider state changes, and then through the invalidate () method to notify the system redraw.
Sixth step:
We do this custom control is for the user to use, now this is no use, the user can not use, so you could set the listener to provide external interface.
/**
* SwitchView Switch Listener Interface
*
* *
/interface Onswitchchangedlistener {public
void Onswitchchange ( Boolean isOpen);
}
/**
* Set SwitchView State monitor
*
/public void Setonchangelistener (Onswitchchangedlistener listener) {
Switchlistener = listener;
}
The Boolean value in this listener needs to be assigned, and when it is assigned, it should be assigned a value when it is lifted or empty, because that is when the switch button is actually turned on or off.
Seventh Step:
This is the step to use to define this custom control in the layout file
<com.example.custom.switchview
minguo:background= "@drawable/switch_background"
minguo:slide= "@ Drawable/slide_button_background "
android:id=" @+id/switchview "
android:layout_width=" Wrap_content "
android:layout_height= "Wrap_content"/>
Using a well-defined view should be used, not to look at the "Android Development notes" custom combo control.
Core code:
Layout file
<linearlayout xmlns:android= "http://schemas.android.com/apk/res/android"
xmlns:minguo= "http:// Schemas.android.com/apk/res/com.example.custom "
xmlns:tools=" Http://schemas.android.com/tools "
Android : layout_width= "match_parent"
android:layout_height= "match_parent"
tools:context= " Com.example.custom.MainActivity ">
<com.example.custom.switchview
minguo:background=" @drawable Switch_background "
minguo:slide=" @drawable/slide_button_background "
android:id=" @+id/switchview
" Android:layout_width= "Wrap_content"
android:layout_height= "wrap_content"/>
</LinearLayout>
Custom View:SwitchView.java
/** * Custom Switch button * @author Administrator * * */public class SwitchView extends View {//Background picture and slider picture private Bitmap back
Groundbitmap,switchslide;
Brush private Paint Paint;
Get the X coordinate (click, move, lift) private float currentx;
Determines whether the switch is open with a token bit private Boolean isOpen = false;
Switch on and off the listener private Onswitchchangedlistener Switchlistener; Four states of the slider public static final int state_down = 1; When pressed, public static final int state_move = 2; When moving the public static final int state_up = 3; When raised, public static final int state_none = 0;
Empty time (that is, nothing dry)//Mark status (default is null state) private int state = State_none;
Public SwitchView {super (context,null);
Public SwitchView (context, AttributeSet attrs) {Super (context, attrs);
Get the custom attribute TypedArray ta = context.obtainstyledattributes (attrs, r.styleable.switchview_attrs);
Get the value of the custom field drawable Switchbackground = ta.getdrawable (R.styleable.switchview_attrs_background); Drawable Switchview_Slide = ta.getdrawable (r.styleable.switchview_attrs_slide);
Set the value to the corresponding component Backgroundbitmap = Convertdrawable2bitmapsimple (Switchbackground);
Switchslide = Convertdrawable2bitmapsimple (switchview_slide); ///Convert drawable to Bitmap public Bitmap convertdrawable2bitmapsimple (drawable drawable) {bitmapdrawable BD = (BITMAPD
rawable) drawable;
return Bd.getbitmap (); //control the size of the control @Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {if (backgroundbitm
AP!= null) {//the size of the control is set to the size of the background setmeasureddimension (Backgroundbitmap.getwidth (), Backgroundbitmap.getheight ());
}else {super.onmeasure (Widthmeasurespec, Heightmeasurespec); The protected void OnDraw (Canvas Canvas) {///background is empty to draw the background if (Backgroundbitmap!=) when the style of the Drawing Control @Override
L) {paint = new paint (); The first parameter represents the bitmap//second parameter that needs to be drawn to represent the bitmap left margin///The third parameter represents the bitmap top edge off the control's top margin//fourth parameter represents the brush Canvas.drawbitma P (backgroundbItmap, 0, 0, paint); The switch (state) {case State_down://Press and move trigger events are all the same, moving the slider to State_move://When the pressed or moved coordinates are greater than half the slider width, the slider right Move if (CurrentX > Switchslide.getwidth ()/2f) {//Slide the slider to the right (redraw the position of the slider) float left = Currentx-switch
Slide.getwidth ()/2f; Prevents the slider from moving outside the background, the largest is the right side of the slider and the right of the background (that is, the maximum from the left is the background width-the slider width) float maxleft = Backgroundbitmap.getwidth ()-Switchslide.getwidth ()
;
if (Left > Maxleft) {left = Maxleft;
} canvas.drawbitmap (Switchslide, left, 0, paint); The slider does not move when the coordinates pressed or moved are less than half the width of the slider}else if (CurrentX < Switchslide.getwidth ()/2f) {//Let the slider not move Canvas.dra
Wbitmap (switchslide, 0, 0, paint);
} break;
Case State_none://Empty or lift the slider as far as the left or right cases STATE_UP://If it is open, move the slider to the right and pass the open state to the listener if (IsOpen) {
if (Switchlistener!= null) {Switchlistener.onswitchchange (true); } canvas.drawbitmap (Switchslide, backGroundbitmap.getwidth ()-switchslide.getwidth (), 0, paint); If it is closed, the slider is turned to the left and the shutdown state is passed to the listener}else {if (Switchlistener!= null) {Switchlistener.onswitchchange (FA
LSE);
} canvas.drawbitmap (switchslide, 0, 0, paint);
} break;
Default:break; @Override public boolean ontouchevent (Motionevent event) {switch (event.getaction ()) {case Motionevent .
Action_down:currentx = Event.getx ();
Modifies the mark bit to the pressed state = State_down;
Notifies the system to redraw the interface invalidate ();//in the main thread//postinvalidate ();//break in the child thread;
Case MotionEvent.ACTION_MOVE:currentX = Event.getx ();
Modify the mark bit to move state = State_move;
Invalidate ();
Break
Case MotionEvent.ACTION_UP:currentX = Event.getx ();
Mark as modified to lift state = state_up; Set to open if (CurrentX > Backgroundbitmap.getwidth ()/2f) {//slider to the right, open IsOpen = tru When lifting coordinates are greater than half the background width
EThe raised coordinates are less than the background width coordinates and are set to the closed state}else if (CurrentX < Backgroundbitmap.getwidth ()) {//slider on the left, close the IsOpen
= false;
} invalidate ();
Break
return true; /** * SwitchView Switch Listener Interface * * * * * interface Onswitchchangedlistener {public void Onswitchchange (Boolean
IsOpen); /** * Set SwitchView State Monitor */public void Setonchangelistener (Onswitchchangedlistener listener) {Switchl
Istener = listener;
}
}
Mainactivity.java
public class Mainactivity extends activity {
private SwitchView SwitchView;
@Override
protected void onCreate (Bundle savedinstancestate) {
super.oncreate (savedinstancestate);
Setcontentview (r.layout.activity_main);
SwitchView = (SwitchView) Findviewbyid (R.id.switchview);
Switchview.setonchangelistener (New Onswitchchangedlistener () {
@Override public
void Onswitchchange ( Boolean IsOpen) {
if (isOpen) {
//The logical toast.maketext when the switch is turned on
(mainactivity.this, "the switch is turned on", Toast.length_ LONG). Show ();
else {
///Turn off Switch logic
toast.maketext (mainactivity.this, "switch Off", Toast.length_long). Show ():}
}
;
}
}
Everyone seems so simple a write so much, in fact, we learn this is not to write this, than this good open source more is, but in order to learn this thinking and thinking, we hurriedly try it!
Thank you for your reading, and hope you can continue to pay attention to the more wonderful content of the cloud-dwelling community.