English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
First, let me show you the effect diagram:
Don't know how everyone feels about the effect diagram, personally, I think it's quite good. Friends who are interested can refer to the implementation code.
public class ToggleButton extends View { private SpringSystem springSystem; private Spring spring; /** */ private float radius; /** Open color*/ private int onColor = Color.parseColor("#4ebb7f); /** Close color*/ private int offBorderColor = Color.parseColor("#dadbda"); /** Gray with color*/ private int offColor = Color.parseColor("#ffffff"); /** Handle color*/ private int spotColor = Color.parseColor("#ffffff"); /** Border color*/ private int borderColor = offBorderColor; /** Pen*/ private Paint paint ; /** Switch state*/ private boolean toggleOn = false; /** Border size*/ private int borderWidth = 2; /** Vertical center*/ private float centerY; /** The starting and ending positions of the button*/ private float startX, endX; /** The minimum and maximum values of the handle X position*/ private float spotMinX, spotMaxX; /**Handle size */ private int spotSize ; /** Handle X position*/ private float spotX; /** Height of the internal gray strip when closed*/ private float offLineWidth; /** */ private RectF rect = new RectF(); /** Default animation is used*/ private boolean defaultAnimate = true; /** Whether the default state is open*/ private boolean isDefaultOn = false; private OnToggleChanged listener; private ToggleButton(Context context) { super(context); } public ToggleButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setup(attrs); } public ToggleButton(Context context, AttributeSet attrs) { super(context, attrs); setup(attrs); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); spring.removeListener(springListener);} } public void onAttachedToWindow() { super.onAttachedToWindow(); spring.addListener(springListener); } public void setup(AttributeSet attrs) { paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setStyle(Style.FILL); paint.setStrokeCap(Cap.ROUND); springSystem = SpringSystem.create(); spring = springSystem.createSpring(); spring.setSpringConfig(SpringConfig.fromOrigamiTensionAndFriction(50, 7)); this.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { toggle(defaultAnimate); } }); TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.ToggleButton); offBorderColor = typedArray.getColor(R.styleable.ToggleButton_tbOffBorderColor, offBorderColor); onColor = typedArray.getColor(R.styleable.ToggleButton_tbOnColor, onColor); spotColor = typedArray.getColor(R.styleable.ToggleButton_tbSpotColor, spotColor); offColor = typedArray.getColor(R.styleable.ToggleButton_tbOffColor, offColor); borderWidth = typedArray.getDimensionPixelSize(R.styleable.ToggleButton_tbBorderWidth, borderWidth); defaultAnimate = typedArray.getBoolean(R.styleable.ToggleButton_tbAnimate, defaultAnimate); isDefaultOn = typedArray.getBoolean(R.styleable.ToggleButton_tbAsDefaultOn, isDefaultOn); typedArray.recycle(); borderColor = offBorderColor; if (isDefaultOn) { toggleOn(); } } public void toggle() { toggle(true); } public void toggle(boolean animate) { toggleOn = !toggleOn; takeEffect(animate); if(listener != null){ listener.onToggle(toggleOn); } } public void toggleOn() { setToggleOn(); if(listener != null){ listener.onToggle(toggleOn); } } public void toggleOff() { setToggleOff(); if(listener != null){ listener.onToggle(toggleOn); } } /** * Set the display style to open without triggering the toggle event */ public void setToggleOn() { setToggleOn(true); } /** * @param animate asd */ public void setToggleOn(boolean animate){ toggleOn = true; takeEffect(animate); } /** * Set the display style to closed without triggering the toggle event */ public void setToggleOff() { setToggleOff(true); } public void setToggleOff(boolean animate) { toggleOn = false; takeEffect(animate); } private void takeEffect(boolean animate) { if(animate){ spring.setEndValue(toggleOn ? 1 : 0); } //Here, spring is not called, so the current value in spring has not changed. We need to set it here to synchronize the current values on both sides spring.setCurrentValue(toggleOn ? 1 : 0); calculateEffect(toggleOn ? 1 : 0); } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { final int widthMode = MeasureSpec.getMode(widthMeasureSpec); final int heightMode = MeasureSpec.getMode(heightMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); Resources r = Resources.getSystem(); if(widthMode == MeasureSpec.UNSPECIFIED || widthMode == MeasureSpec.AT_MOST){ widthSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 50, r.getDisplayMetrics()); widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY); } if(heightMode == MeasureSpec.UNSPECIFIED || heightSize == MeasureSpec.AT_MOST){ heightSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 30, r.getDisplayMetrics()); heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY); } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); final int width = getWidth(); final int height = getHeight(); radius = Math.min(width, height) * 0.5f; centerY = radius; startX = radius; endX = width - radius; spotMinX = startX + borderWidth; spotMaxX = endX - borderWidth; spotSize = height - 4 * borderWidth; spotX = toggleOn &63; spotMaxX : spotMinX; offLineWidth = 0; } SimpleSpringListener springListener = new SimpleSpringListener(){ @Override public void onSpringUpdate(Spring spring) { final double value = spring.getCurrentValue(); calculateEffect(value); } }; private int clamp(int value, int low, int high) { return Math.min(Math.max(value, low), high); } @Override public void draw(Canvas canvas) { // rect.set(0, 0, getWidth(), getHeight()); paint.setColor(borderColor); canvas.drawRoundRect(rect, radius, radius, paint); if(offLineWidth > 0){ final float cy = offLineWidth * 0.5f; rect.set(spotX - cy, centerY - cy, endX + cy, centerY + cy); paint.setColor(offColor); canvas.drawRoundRect(rect, cy, cy, paint); } rect.set(spotX - 1 - radius, centerY - radius, spotX + 1.1f + radius, centerY + radius); paint.setColor(borderColor); canvas.drawRoundRect(rect, radius, radius, paint); final float spotR = spotSize * 0.5f; rect.set(spotX - spotR, centerY - spotR, spotX + spotR, centerY + spotR); paint.setColor(spotColor); canvas.drawRoundRect(rect, spotR, spotR, paint); } /** * @param value */ private void calculateEffect(final double value) { final float mapToggleX = (float) SpringUtil.mapValueFromRangeToRange(value, 0, 1, spotMinX, spotMaxX); spotX = mapToggleX; float mapOffLineWidth = (float) SpringUtil.mapValueFromRangeToRange(1 - value, 0, 1, 10, spotSize); offLineWidth = mapOffLineWidth; final int fb = Color.blue(onColor); final int fr = Color.red(onColor); final int fg = Color.green(onColor); final int tb = Color.blue(offBorderColor); final int tr = Color.red(offBorderColor); final int tg = Color.green(offBorderColor); int sb = (int) SpringUtil.mapValueFromRangeToRange(1 - value, 0, 1, fb, tb); int sr = (int) SpringUtil.mapValueFromRangeToRange(1 - value, 0, 1, fr, tr); int sg = (int) SpringUtil.mapValueFromRangeToRange(1 - value, 0, 1, fg, tg); sb = clamp(sb, 0, 255); sr = clamp(sr, 0, 255); sg = clamp(sg, 0, 255); borderColor = Color.rgb(sr, sg, sb); postInvalidate(); } /** * @author ThinkPad * */ public interface OnToggleChanged{ /** * @param on = = */ public void onToggle(boolean on); } public void setOnToggleChanged(OnToggleChanged onToggleChanged) { listener = onToggleChanged; } public boolean isAnimate() { return defaultAnimate; } public void setAnimate(boolean animate) { this.defaultAnimate = animate; } }
Don't forget to customize the attributes: attrs.xml
<&63;xml version="1.0" encoding="utf-8"-8"&63> <resources> <declare-styleable name="ToggleButton"> <attr name="tbBorderWidth" format="dimension">/> <attr name="tbOffBorderColor" format="reference|color">/> <attr name="tbOffColor" format="reference|color">/> <attr name="tbOnColor" format="reference|color">/> <attr name="tbSpotColor" format="reference|color">/> <attr name="tbAnimate" format="reference|boolean">/> <attr name="tbAsDefaultOn" format="reference|boolean">/> </declare-styleable> </resources>
main.xml
<&63;xml version="1.0" encoding="utf-8"-8"&63> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:toggle="http://schemas.android.com/apk/res-auto" android:orientation="vertical" > <LinearLayout android:layout_marginTop="10dp" android:layout_width="match_parent" android:gravity="center_horizontal" android:layout_height="wrap_content"> <com.example.ekikousei.view.ToggleButton android:id="@"+id/mToggleButton01" android:layout_width="54dp" android:layout_height="30dp"> </com.example.ekikousei.view.ToggleButton> </LinearLayout> <LinearLayout android:layout_marginTop="10dp" android:layout_width="match_parent" android:gravity="center_horizontal" android:layout_height="wrap_content"> <com.example.ekikousei.view.ToggleButton android:id="@"+id/mToggleButton02" android:layout_width="54dp" android:layout_height="30dp" toggle:tbBorderWidth="2dp" toggle:tbOffBorderColor="#000" toggle:tbOffColor="#ddd" toggle:tbOnColor="#f00" toggle:tbSpotColor="#00f"> </com.example.ekikousei.view.ToggleButton> </LinearLayout> </LinearLayout>
Maintivity
public class MainActivity extends Activity { private ToggleButton mToggleButton01; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mToggleButton01 = (ToggleButton) findViewById(R.id.mToggleButton01); mToggleButton01.setOnToggleChanged(new ToggleButton.OnToggleChanged() { @Override public void onToggle(boolean on) { if (on) { Toast.makeText(MainActivity.this, "On", Toast.LENGTH_SHORT).show(); } Toast.makeText(MainActivity.this, "Default Off", Toast.LENGTH_SHORT).show(); } } }); } }
Click here to read more:Click here to download studio
The above is what the editor introduces to everyone about Android's imitation of Apple iOS6Switch button, hope it helps everyone. If you have any questions, please leave a message, the editor will reply to everyone in time. I also want to express my sincere gratitude to everyone for their support of the Yanaohua tutorial website!
Statement: The content of this article is from the Internet, the copyright belongs to the original author, the content is contributed and uploaded by Internet users spontaneously, this website does not own the copyright, has not been manually edited, and does not bear relevant legal liability. If you find any content suspected of copyright infringement, please send an email to: notice#w3Please send an email to codebox.com (replace # with @ when sending an email) to report violations, and provide relevant evidence. Once verified, this site will immediately delete the content suspected of infringement.