转载请注明出处:http://blog.csdn.net/llew2011/article/details/51668407
了解iOS的同学应该知道在iOS中有个UISliderBar控件,在iPhone手机中的设置文字大小中使用了该控件。近来产品提的需求中有一个是更改APP中部分字体大小,虽然技术难度不大但工作量还是有的,思路是利用LayoutInflater.Factory实现的(如果你对LayoutInflater.Factory不熟悉可以阅读之前写的Android 源码系列之<四>从源码的角度深入理解LayoutInflater.Factory之主题切换系类文章)。UI是参考iOS的UISliderBar设计的,而Android系统并没有提供直接符合要求的控件,于是动手写了个类似UISliderBar的控件,我给它起名为FontSliderBar,运行效果如下所示:
好了,开始讲解如果实现该效果吧,开始实现该功能之前我们先分析一下iOS的UISliderBar的运行效果,根据iOS的截图图左一可以知道该控件有刻度条,在刻度条的上方还有一个可拖动的圆球,因此FontSliderBar可以做一下拆分,把画表刻度尺的功能单独提取出来用Bar来表示,拖动的圆球用Thumb来表示,拆分图如下所示:
根据拆分图我们来分析一下Thumb和Bar应该具有什么属性和功能吧。
- Thumb功能分析
Thumb的职责就是负责在屏幕上进行绘制操作,既然进行绘制操作,肯定需要画布Canvas实例,获取Canvas实例可以通过方法传递进来;其次绘制的时候绘制在哪,所以Thumb需要属性坐标XY(其中Thumb的X坐标是可更改的而Y坐标是不可更改的);再次Thumb在绘制圆的时候绘制多大,当手指摁下绘制成什么颜色手指抬起后又要绘制成什么颜色,所以Thumb需要有半径属性radius和表示手指摁下和抬起的颜色属性normalColor和pressedColor。好了,经过分析,我们的Thumb对象算是可以构建出来了,代码如下:
Thumb的代码很简单,需要说明的是在Thumb中新加了一个mTouchDelegate属性,该属性模拟了Android系统中的TouchDelegate特性(有不熟悉View中的TouchDelegate原理的请自行查阅源码,这个不在做详述了),使用场景就是当圆的半径太小的时候可能手指点击不住,这样会影响用户体验,所以就设置了mTouchDelete属性,它表示手指触摸的最小范围。public class Thumb { private static final float MINIMUM_TARGET_RADIUS = 50; private final float mTouchZone; private boolean mIsPressed; private final float mY; private float mX; private Paint mPaintNormal; private Paint mPaintPressed; private float mRadius; private int mColorNormal; private int mColorPressed; public Thumb(float x, float y, int colorNormal, int colorPressed, float radius) { mRadius = radius; mColorNormal = colorNormal; mColorPressed = colorPressed; mPaintNormal = new Paint(); mPaintNormal.setColor(mColorNormal); mPaintNormal.setAntiAlias(true); mPaintPressed = new Paint(); mPaintPressed.setColor(mColorPressed); mPaintPressed.setAntiAlias(true); mTouchZone = (int) Math.max(MINIMUM_TARGET_RADIUS, radius); mX = x; mY = y; } public void setX(float x) { mX = x; } public float getX() { return mX; } public boolean isPressed() { return mIsPressed; } public void press() { mIsPressed = true; } public void release() { mIsPressed = false; } public boolean isInTargetZone(float x, float y) { if (Math.abs(x - mX) <= mTouchZone && Math.abs(y - mY) <= mTouchZone) { return true; } return false; } public void draw(Canvas canvas) { if (mIsPressed) { canvas.drawCircle(mX, mY, mRadius, mPaintPressed); } else { canvas.drawCircle(mX, mY, mRadius, mPaintNormal); } } public void destroyResources() { if(null != mPaintNormal) { mPaintNormal = null; } if(null != mPaintPressed) { mPaintPressed = null; } } }
- Bar功能分析
Bar的功能是绘制刻度尺,竟然是绘制刻度尺首先和Thumb一样需要有XY坐标和Canvas实例;其次该刻度尺有多长,有多少个刻度,刻度的高度是多少,刻度尺的颜色是什么样的;再次刻度尺上边还有一个文字,文字的大小,文字的颜色等都需要知道,通过这样的分析,我们就可以抽象出Bar对象了,代码如下:public class Bar { private Paint mBarPaint; private Paint mTextPaint; private final float mLeftX; private final float mRightX; private final float mY; private final float mPadding; private int mSegments; private float mTickDistance; private final float mTickHeight; private final float mTickStartY; private final float mTickEndY; public Bar(float x, float y, float width, int tickCount, float tickHeight, float barWidth, int barColor,int textColor, int textSize, int padding) { mLeftX = x; mRightX = x + width; mY = y; mPadding = padding; mSegments = tickCount - 1; mTickDistance = width / mSegments; mTickHeight = tickHeight; mTickSta