Android 自定义带动画效果的开关按钮
2016-08-13 11:35
417 查看
自定义带动画效果的开关按钮
一个自定义控制开关的控件,简单实用,效果特别棒。项目中常会用到,比那种用两张图片做按钮背景,selector选择的方式,视觉效果好很多。忘了是以前从哪找的了,本着开源的精神整理了一下分享出来。好了,废话不多说,先展示效果图:
Github 项目地址:https://github.com/xiaosong520/SwitchButtonDemo.git
步骤:
1.创建SwitchButton类添加到自己的项目中:
2.在项目res - values目录下 - 找到 attrs.xml 文件,在resource中间添加如下代码:
3.在XML布局文件中使用控件(路径引用需改成SwitchButton类所在目录):
控件的属性介绍:
borderWidth 描边宽度
offBorderColor 关闭状态下描边的颜色
offColor 关闭状态的颜色
onColor 打开状态的颜色
spotColor 控件中间的圆点的颜色
animate 是否打开动画效果
4.在Activity中使用:
4.1绑定控件:
如果使用ButterKinfe库的话:
@Bind(R.id.switchButton) SwitchButton switchButton;
findViewById的方式:
SwitchButton switchButton = (SwitchButton)findViewById(R.id.switchButton);
4.2使用控件:
5.没有第五步了,已经大功告成~ 有问题欢迎call我,一起讨论~
一个自定义控制开关的控件,简单实用,效果特别棒。项目中常会用到,比那种用两张图片做按钮背景,selector选择的方式,视觉效果好很多。忘了是以前从哪找的了,本着开源的精神整理了一下分享出来。好了,废话不多说,先展示效果图:
Github 项目地址:https://github.com/xiaosong520/SwitchButtonDemo.git
步骤:
1.创建SwitchButton类添加到自己的项目中:
/** * @TODO<自定义选择开关按钮> * @author 小嵩 * @date 2016-8-5 09:57:29 */ public class SwitchButton extends View{ /** 圆角大小*/ private float radius; /** 开启颜色*/ private int onColor = Color.parseColor("#4ebb7f"); /** 关闭颜色*/ private int offBorderColor = Color.parseColor("#dadbda"); /** 灰色带颜色*/ private int offColor = Color.parseColor("#ffffff"); /** 手柄颜色*/ private int spotColor = Color.parseColor("#ffffff"); /** 边框颜色*/ private int borderColor = offBorderColor; /** 画笔*/ private Paint paint ; /** 开关状态*/ private boolean toggleOn = false; /** 边框大小*/ private int borderWidth = 2; /** 垂直中心*/ private float centerY; /** 按钮的开始和结束位置*/ private float startX, endX; /** 手柄X位置的最小和最大值*/ private float spotMinX, spotMaxX; /**手柄大小 */ private int spotSize ; /** 手柄X位置*/ private float spotX; /** 关闭时内部灰色带高度*/ private float offLineWidth; /** */ private RectF rect = new RectF(); /** 默认使用动画*/ private boolean defaultAnimate = true; private OnToggleChanged listener; private SwitchButton(Context context) { super(context); } public SwitchButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); setup(attrs); } public SwitchButton(Context context, AttributeSet attrs) { super(context, attrs); setup(attrs); } public void setup(AttributeSet attrs) { paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setStyle(Style.FILL); paint.setStrokeCap(Cap.ROUND); this.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { toggle(defaultAnimate); } }); TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.SwitchButton); offBorderColor = typedArray.getColor(R.styleable.SwitchButton_offBorderColor, offBorderColor); onColor = typedArray.getColor(R.styleable.SwitchButton_onColor, onColor); spotColor = typedArray.getColor(R.styleable.SwitchButton_spotColor, spotColor); offColor = typedArray.getColor(R.styleable.SwitchButton_offColor, offColor); borderWidth = typedArray.getDimensionPixelSize(R.styleable.SwitchButton_borderWidth, borderWidth); defaultAnimate = typedArray.getBoolean(R.styleable.SwitchButton_animate, defaultAnimate); typedArray.recycle(); borderColor = offBorderColor; } 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); } } /** * 设置显示成打开样式,不会触发toggle事件 */ public void setToggleOn() { setToggleOn(true); } /** * @param animate */ public void setToggleOn(boolean animate){ toggleOn = true; takeEffect(animate); } /** * 设置显示成关闭样式,不会触发toggle事件 */ public void setToggleOff() { setToggleOff(true); } public void setToggleOff(boolean animate) { toggleOn = false; takeEffect(animate); } private void takeEffect(boolean animate) { if(animate){ slide(); }else{ 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 ? spotMaxX : spotMinX; offLineWidth = 0; } private void slide(){ Animation animation = new Animation() { @Override protected void applyTransformation(float interpolatedTime, Transformation t) { if(toggleOn){ calculateEffect(interpolatedTime); }else{ calculateEffect(1-interpolatedTime); } } }; animation.setDuration(200); clearAnimation(); startAnimation(animation); } 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) mapValueFromRangeToRange(value, 0, 1, spotMinX, spotMaxX); spotX = mapToggleX; float mapOffLineWidth = (float) 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) mapValueFromRangeToRange(1 - value, 0, 1, fb, tb); int sr = (int) mapValueFromRangeToRange(1 - value, 0, 1, fr, tr); int sg = (int) 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(); } 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; } /** * Map a value within a given range to another range. * @param value the value to map * @param fromLow the low end of the range the value is within * @param fromHigh the high end of the range the value is within * @param toLow the low end of the range to map to * @param toHigh the high end of the range to map to * @return the mapped value */ public static double mapValueFromRangeToRange( double value, double fromLow, double fromHigh, double toLow, double toHigh) { double fromRangeSize = fromHigh - fromLow; double toRangeSize = toHigh - toLow; double valueScale = (value - fromLow) / fromRangeSize; return toLow + (valueScale * toRangeSize); } }
2.在项目res - values目录下 - 找到 attrs.xml 文件,在resource中间添加如下代码:
<declare-styleable name="SwitchButton"> <attr name="borderWidth" format="dimension"> </attr> <attr name="offBorderColor" format="reference|color"> </attr> <attr name="offColor" format="reference|color"> </attr> <attr name="onColor" format="reference|color"> </attr> <attr name="spotColor" format="reference|color"> </attr> <attr name="animate" format="reference|boolean"> </attr> </declare-styleable>
3.在XML布局文件中使用控件(路径引用需改成SwitchButton类所在目录):
<com.ui.widget.view.SwitchButton android:id="@+id/switchButton" android:layout_width="45dp" android:layout_height="25dp" app:borderWidth="0.8dp" app:offBorderColor="@color/light_gray" app:offColor="@color/common_white" app:onColor="@color/common_light_blue" app:spotColor="@color/common_white" app:animate="true" android:layout_margin="20dp" />
控件的属性介绍:
borderWidth 描边宽度
offBorderColor 关闭状态下描边的颜色
offColor 关闭状态的颜色
onColor 打开状态的颜色
spotColor 控件中间的圆点的颜色
animate 是否打开动画效果
4.在Activity中使用:
4.1绑定控件:
如果使用ButterKinfe库的话:
@Bind(R.id.switchButton) SwitchButton switchButton;
findViewById的方式:
SwitchButton switchButton = (SwitchButton)findViewById(R.id.switchButton);
4.2使用控件:
switchButton.setToggleOn(false);//默认打开。如果参数传false,则打开页面初始化时不会有动画效果(改变状态还是会有动画) switchButton.setOnToggleChanged(new SwitchButton.OnToggleChanged(){ @Override public void onToggle(boolean isOn) { //处理自己的逻辑 showToast( "SwitchButton"+isOn); } });
5.没有第五步了,已经大功告成~ 有问题欢迎call我,一起讨论~
相关文章推荐
- Android 自定义带动画效果的开关按钮
- Android UI设计之<二>自定义SwitchButton开关,实现类似IOS中UISwitch的动画效果
- Android中动画实现单击按钮控制开屏关屏效果(系统animation实现、scrollTo实现、自定义scrollTo实现)
- Android进阶——自定义View之继承系统控件实现自带删除按钮动画效果和软键盘自动悬浮于文本框下方
- Android上Path应用左下角按钮动画效果demo原型
- [Android]点击按钮进入下一个Activity时显示动画效果
- android 自定义动画效果 一
- 自定义带动画的开关按钮
- 使用ToggleButton和StackPanel+Border实现圆角开关按钮动画效果
- Android中ImageButton自定义按钮的按下效果的代码实现方法
- Android仿Path按钮动画效果 PathButton
- Android实现按钮从两边移到中间动画效果(网上整理)
- android自定义ImageButton按钮的按下效果的代码实现
- Android自定义Activity酷炫的动画跳转效果
- 【Android开发那点破事】定制返回按钮的动画效果。
- [Android]点击按钮进入下一个Activity时显示动画效果
- moo弹出框 改进版 css外置 背景用图片 大小任意缩放 圆角 插入任意内容 自定义按钮 回车空格esc支持 滚动支持 动画开关
- 转载 :Android中ImageButton自定义按钮的按下效果的代码实现方法,附网上2种经典解决方法。
- Android 实现 按钮从两边移到中间动画效果
- android 自定义按钮效果