ToggleButton自定义View学习
2015-06-04 11:28
357 查看
1.
ToggleButton项目地址
2.
rebound项目地址
3.
本地下载
4. 相关参考
android中onMeasure初看,深入理解布局之一!
Android 自定义View onMeasure方法的实现
ANDROID自定义视图——onMeasure,MeasureSpec源码 流程 思路详解
Android视图绘制流程完全解析,带你一步步深入了解View(二)
昨天学习了ToggleButton,一个挺好看的开关。并且自己重新实现了一遍。感觉还是很不错的。今早又重新复习了自定义View的相关知识,包括绘制的流程及回调函数的作用。想到不知怎样才能达到一个高度,有些失落。
这个View的效果图是这样的(图来自这里):
看起来很舒服,但是是怎样实现的呢?实现起来还是需要思考的。结合项目的源码,可以把这个View分解为几部分。这也提供了一种思路,要实现一个复杂漂亮的控件,是一层一层效果叠加起来。第一层是最里边的RoundRect,它的效果是由灰色变成青色(手机里还没了解哪个制作gif软件好用)。但是这个变化的过程是如何产生的,这也是整个View最核心的部分。包括滑动过程的控制。作者使用了一个开源的库,是由Facebook团队开发维护的rebound。它的作用是模拟物理的弹簧力的效果,想象一下,一根弹簧固定立起来,把手压下去,当手放开时,弹簧的伸缩变化。即是rebound所实现的,这里涉及到两个系数,就是张力tension和摩擦力friction。rebound的使用可以参考项目的例子或者作者的写法。先是创建Spring实例:
然后在适当的位置进行监听和解除监听:
其中,传入的mSpringListener监听对象继承了SimpleSpringListener,关键在于它的onSpringUdate(Spring spring)方法,我们要重写它的方法。并且进行映射。其中关键的函数是:
它传入了从spring中获取的currentValue,映射的起始范围,和映射的结束范围。返回的值是物理的弹簧力学模型。仔细观察上面开关中间的滑动圆形,可以看到它的伸缩性。我们应该去它的文档说明网站,里边有介绍如何使用,和一个非常形象的演示系统。便于理解其中的效果。其中,我想到了之前没有深入学习的属性动画中的插值器,这个应该也是做同样的事情。等下要去学习弄懂。这样最重要的事情别人就帮我们做好了。而我们现在,只要在监听回调函数中,进行draw绘画所需属性的修改,就可以完成这个自定义View。但是其中,还是有一些涉及到计算的事情,不能搞错。这也是较为重要和繁琐的工作。比如,我们要计算长和宽、可以匹配的最大范围值,外RountRect的半径,内RountRect的半径等:
还有,这段代码应该放在哪个地方。onMeasure和onLayout的作用。当然,这个在给出的参考地址中都有讲解。我们把它放在onLayout函数中,其中相关的只是要获取到getWidth()和getHeight(),其它的都只是纯计算。
现在,我们看第二层绘画,即是一个比第一层图像小一个BorderWidth的内RountRect,并且颜色为白色。打开开关时,它会同时移动到距右边的三分之一,并且缩小。它的移动、缩放的值也是在spring的监听回调函数中改变。第三层是一个圆形的RoundRect,它从左边移动到右边,并且颜色渐变。第四层动画是一个比第三层小一个BorderWidth的圆形RoundRect,颜色为固定的色值,这里为白色,并且同样从左边移动到右边。最后,如果把这四层效果一同绘制,就是上面ToggleButton的效果了。当实现完成后,发现并不是很难,给了自己信心。下面贴几段代码:
①获取自定义的参数值
②Spring中的监听回调:
③onDraw方法中的绘制过程:
ToggleButton项目地址
2.
rebound项目地址
3.
本地下载
4. 相关参考
android中onMeasure初看,深入理解布局之一!
Android 自定义View onMeasure方法的实现
ANDROID自定义视图——onMeasure,MeasureSpec源码 流程 思路详解
Android视图绘制流程完全解析,带你一步步深入了解View(二)
昨天学习了ToggleButton,一个挺好看的开关。并且自己重新实现了一遍。感觉还是很不错的。今早又重新复习了自定义View的相关知识,包括绘制的流程及回调函数的作用。想到不知怎样才能达到一个高度,有些失落。
这个View的效果图是这样的(图来自这里):
看起来很舒服,但是是怎样实现的呢?实现起来还是需要思考的。结合项目的源码,可以把这个View分解为几部分。这也提供了一种思路,要实现一个复杂漂亮的控件,是一层一层效果叠加起来。第一层是最里边的RoundRect,它的效果是由灰色变成青色(手机里还没了解哪个制作gif软件好用)。但是这个变化的过程是如何产生的,这也是整个View最核心的部分。包括滑动过程的控制。作者使用了一个开源的库,是由Facebook团队开发维护的rebound。它的作用是模拟物理的弹簧力的效果,想象一下,一根弹簧固定立起来,把手压下去,当手放开时,弹簧的伸缩变化。即是rebound所实现的,这里涉及到两个系数,就是张力tension和摩擦力friction。rebound的使用可以参考项目的例子或者作者的写法。先是创建Spring实例:
mBaseSpringSystem = SpringSystem.create(); mSpring = mBaseSpringSystem.createSpring(); mSpring.setSpringConfig(SpringConfig.fromOrigamiTensionAndFriction(50, 7));
然后在适当的位置进行监听和解除监听:
@Override protected void onAttachedToWindow() { super.onAttachedToWindow(); mSpring.addListener(mSpringListener); }
@Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); mSpring.removeListener(mSpringListener); }
其中,传入的mSpringListener监听对象继承了SimpleSpringListener,关键在于它的onSpringUdate(Spring spring)方法,我们要重写它的方法。并且进行映射。其中关键的函数是:
mWhileLTScale = (int) SpringUtil.mapValueFromRangeToRange(currentValue, 0, 1, 0, mWhileLTScaleWidth);
它传入了从spring中获取的currentValue,映射的起始范围,和映射的结束范围。返回的值是物理的弹簧力学模型。仔细观察上面开关中间的滑动圆形,可以看到它的伸缩性。我们应该去它的文档说明网站,里边有介绍如何使用,和一个非常形象的演示系统。便于理解其中的效果。其中,我想到了之前没有深入学习的属性动画中的插值器,这个应该也是做同样的事情。等下要去学习弄懂。这样最重要的事情别人就帮我们做好了。而我们现在,只要在监听回调函数中,进行draw绘画所需属性的修改,就可以完成这个自定义View。但是其中,还是有一些涉及到计算的事情,不能搞错。这也是较为重要和繁琐的工作。比如,我们要计算长和宽、可以匹配的最大范围值,外RountRect的半径,内RountRect的半径等:
int width = getWidth(); int height = getHeight(); mWhileLeftMargin = (int) mOffBorderWidth; mWhileTopMargin = (int) mOffBorderWidth; mWhileRightMargin = (int) (width - mOffBorderWidth); mWhileBottomMargin = (int) (height - mOffBorderWidth); mWhileLTScaleWidth = width - (width-(int)mOffBorderWidth*2)/3 - width/15; mWhileRBScaleWidth = (height-(int)mOffBorderWidth*2)/4; mRadius = (Math.min(width, height) ) / 2; mRadius2 = mRadius - mOffBorderWidth; mRadius3 = mRadius2 - mOffBorderWidth; mRectMoveFillLeft = mOffBorderWidth; mRectMoveFillTop = mOffBorderWidth; mRectMoveFillRight = mRectMoveFillLeft + mRadius2 * 2; mRectMoveFillBottom = mOffBorderWidth + mRadius2 * 2; mRectMoveMax = width - mRadius2*2 - mOffBorderWidth;
还有,这段代码应该放在哪个地方。onMeasure和onLayout的作用。当然,这个在给出的参考地址中都有讲解。我们把它放在onLayout函数中,其中相关的只是要获取到getWidth()和getHeight(),其它的都只是纯计算。
现在,我们看第二层绘画,即是一个比第一层图像小一个BorderWidth的内RountRect,并且颜色为白色。打开开关时,它会同时移动到距右边的三分之一,并且缩小。它的移动、缩放的值也是在spring的监听回调函数中改变。第三层是一个圆形的RoundRect,它从左边移动到右边,并且颜色渐变。第四层动画是一个比第三层小一个BorderWidth的圆形RoundRect,颜色为固定的色值,这里为白色,并且同样从左边移动到右边。最后,如果把这四层效果一同绘制,就是上面ToggleButton的效果了。当实现完成后,发现并不是很难,给了自己信心。下面贴几段代码:
①获取自定义的参数值
TypedArray typedArray = null; try { typedArray = context.obtainStyledAttributes(set, R.styleable.ToggleButton); mOnColor = typedArray.getColor(R.styleable.ToggleButton_onColor, mOnColor); mOffColor = typedArray.getColor(R.styleable.ToggleButton_offColor, mOffColor); mOffBorderWidth = typedArray.getDimension(R.styleable.ToggleButton_offBorderWidth, mOffBorderWidth); mOffBorderColor = typedArray.getColor(R.styleable.ToggleButton_offBorderColor, mOffBorderColor); mTension = typedArray.getInteger(R.styleable.ToggleButton_tension, mTension); mResistance = typedArray.getInteger(R.styleable.ToggleButton_resistance, mResistance); } finally { if (typedArray != null ) { typedArray.recycle(); } }
②Spring中的监听回调:
private class SpringListener extends SimpleSpringListener { @Override public void onSpringUpdate(Spring spring) { super.onSpringUpdate(spring); double currentValue = spring.getCurrentValue(); changeEffect(currentValue ); log("currentValue: " + currentValue ); } private void changeEffect(double currentValue) { //得到变化的背景颜色值 int or = Color.red(mOffColor); int og = Color.green(mOffColor); int ob = Color.blue(mOffColor); int dr = Color.red(mOnColor); int dg = Color.green(mOnColor); int db = Color.blue(mOnColor); int cr = (int) SpringUtil.mapValueFromRangeToRange(1-currentValue, 0, 1, dr, or); int cg = (int) SpringUtil.mapValueFromRangeToRange(1-currentValue, 0, 1, dg, og); int cb = (int) SpringUtil.mapValueFromRangeToRange(1-currentValue, 0, 1, db, ob); cr = modify(cr); cg = modify(cg); cb = modify(cb); mCurrentColor = Color.rgb(cr, cg, cb); //改变第二层效果,即白色的内框移动缩小 mWhileLTScale = (int) SpringUtil.mapValueFromRangeToRange(currentValue, 0, 1, 0, mWhileLTScaleWidth); mWhileRBScale = (int) SpringUtil.mapValueFromRangeToRange(currentValue, 0, 1, 0, mWhileRBScaleWidth); log("mWhileLTScale:" + mWhileLTScale + ", mWhileRBScale:" + mWhileRBScale ); //移动的圆圈,第三层 mCurRectMove = SpringUtil.mapValueFromRangeToRange(currentValue, 0, 1, 0, mRectMoveMax); if (Looper.myLooper() == Looper.getMainLooper() ) { invalidate(); } else { postInvalidate(); } } private int modify(int cr) { int t = cr > 0 ? cr : 0; t = t < 255 ? t : 255; return t; } }
③onDraw方法中的绘制过程:
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); log("onDraw()"); mPaint.setColor(mCurrentColor); mOutRect.set(0, 0, getWidth(), getHeight()); canvas.drawRoundRect(mOutRect, mRadius, mRadius, mPaint); mPaint.setColor(Color.parseColor("#FCFCFC") ); //有质感的白色 // mOutRect.set(mWhileLeftMargin+mWhileLTScale, mWhileTopMargin+mWhileLTScale, mWhileRightMargin-mWhileRBScale, mWhileBottomMargin-mWhileRBScale); int left = mWhileLeftMargin+mWhileLTScale; int top = mWhileTopMargin+mWhileRBScale; int right = mWhileRightMargin-mWhileRBScale; int bottom = mWhileBottomMargin-mWhileRBScale; float r2 = mRadius-mOffBorderWidth-mWhileRBScale; log("zb", "mWhileLTScale:" + mWhileLTScale + ", mWhile a801 RBScale:" + mWhileRBScale); log("zb", "left: " + left + ", top: " + top + ", right: " + right + ", bottom :" + bottom ); mOutRect.set(left, top, right, bottom); canvas.drawRoundRect(mOutRect, r2, r2, mPaint); //画第三部分,一个移动变化的圆圈 mPaint.setColor(mCurrentColor); mOutRect.set(mRectMoveFillLeft+(float)mCurRectMove, mRectMoveFillTop, mRectMoveFillRight+(float)mCurRectMove, mRectMoveFillBottom); canvas.drawRoundRect(mOutRect, mRadius, mRadius, mPaint); //画第四部分,最里面的移动的白色圆圈 mPaint.setColor(Color.WHITE); mOutRect.set(mRectMoveFillLeft+(float)mCurRectMove+mOffBorderWidth, mRectMoveFillTop+mOffBorderWidth, mRectMoveFillRight+(float)mCurRectMove-mOffBorderWidth, mRectMoveFillBottom-mOffBorderWidth); canvas.drawRoundRect(mOutRect, mRadius3, mRadius3, mPaint); }
相关文章推荐
- 麻雀虽小五脏俱全 Dojo自定义控件应用
- WinForm自定义控件应用实例
- 百度地图自定义控件分享
- 用javascript添加控件自定义属性解析
- Android自定义控件之仿优酷菜单
- Android自定义表格控件满足人们对视觉的需求
- asp.net 自定义控件实现无刷新上传图片,立即显示缩略图,保存图片缩略图
- asp.net DropDownList自定义控件,让你的分类更清晰
- 如何通过javascript操作web控件的自定义属性
- 自定义模板列在 PostBack 后消失的问题
- android自定义控件实例
- android中播放gif动画之二
- 设置ToggleButton、Switch、CheckBox和RadioButton的显示效果
- 设置ToggleButton、Switch、CheckBox和RadioButton的显示效果
- android面试常见的handler机制 AIDL机制 高级控件UI 内存优化
- Android Zxing条码扫描自定义控件(附代码)
- winform控件显示及闪烁问题
- 自定义控件-1.基本用法
- Android自定义控件之旅(一)滑动开关
- 第二章(3)自定义控件