尊重原创转载请注明:http://blog.csdn.net/bfbx5173/article/details/45191147
saber 镇楼
自学android差不多有一年了,从最初的小白菜鸟,摸爬滚打,看大神们的博客,android官网的api,某网站的视频教学,github开源项目。奋斗这么久隐隐感觉自己可以脱离新手的身份了,交出这篇文章权当作andriod小学水准的毕业典礼。
iOS SwitchButton。 说实话功能也不过就个开关功能而已。但是为什么让人感觉不错,因为效果看起来赏心悦目呀:
~~~~~~~~~~~~~~~~~
好了,为了实现它,首先要分析它。
这个按钮被我玩来玩去最后静止的时候都会停留在下面的样子:
那么怎么把这个实现出来呢?观察一番会发现上图是极其规律的,只是一些基础几何图形的组合。所以具备纯代码实现可能性,同时如果用图片实现这个效果需要对应的png文件辅助,相信大家一定觉得麻烦。
那么就把它画出来!如何画出来的分析路线:
1. 位置固定不变的背景,像田径场一样的形状。
2. 圆圆的按钮,压在“田径场”上面。 【之后背景全称作"田径场",比较形象,不服solo 囧】
3. 淡淡的按钮阴影,夹在他们之间。
ps:哎,我还是分析的那么透彻,赞一个。
开始动手!新建
public class SwitchView extends View {
public SwitchView(Context context) {
this(context, null);
}
public SwitchView(Context context, AttributeSet attrs) {
super(context, attrs);
setLayerType(LAYER_TYPE_SOFTWARE, null);
}
}
之后为自己确定大小~ 截图量了一下 算上阴影宽高比例是 149:92 。即 height = width * 0.65 左右
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = (int) (widthSize * 0.65f);
setMeasuredDimension(widthSize, heightSize);
}
绘制~
@Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawColor(0xffcccccc);
}
好哒,通向胜利的第一步已经完成了。
ps: 如果我说,剩下的大家自己思考,你们不会打我吧。
第二步,画田径场!
private final Paint paint = new Paint();
private final Path sPath = new Path();
private int mWidth, mHeight;
private float sWidth, sHeight;
private float sLeft, sTop, sRight, sBottom;
private float sCenterX, sCenterY;
@Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = w; // 视图自身宽度
mHeight = h; // 视图自身高度
sLeft = sTop = 0; // 田径场 左和上的坐标
sRight = mWidth; // 田径场 右占自身的全部
sBottom = mHeight * 0.8f; // 田径场底部 占全身的百分之八十, 下面预留百分之二十的空间画按钮阴影。
sWidth = sRight - sLeft; // 田径场的宽度
sHeight = sBottom - sTop; // 田径场的高度
sCenterX = (sRight + sLeft) / 2; // 田径场的X轴中心坐标
sCenterY = (sBottom + sTop) / 2; // 田径场的Y轴中心坐标
RectF sRectF = new RectF(sLeft, sTop, sBottom, sBottom);
sPath.arcTo(sRectF, 90, 180);
sRectF.left = sRight - sBottom;
sRectF.right = sRight;
sPath.arcTo(sRectF, 270, 180);
sPath.close(); // path准备田径场的路径
}
@Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setAntiAlias(true);
paint.setStyle(Style.FILL);
paint.setColor(0xffcccccc);
canvas.drawPath(sPath, paint); // 画出田径场
paint.reset();
}
由于田径场不是基础规则的几何图形,只好交给万能的path对象啦。 path 左右加两段圆弧中间一连接,感谢api朋友 [arcTo]
值得注意的是预留出按钮阴影的位置。
既然都做到这个程度了,那就把背景的效果做完嘛。有什么效果呢。
额,这么搓逼,不过确实是这个效果,也许整体完成后就是另一番风景吧。orz
这个效果用大腿想象就知道是点击触发的,既然如此:
@Override public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
return true;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
sAnim = 1; // 动画标示
isOn = !isOn; // 状态标示 , 开关
invalidate();
break;
}
return super.onTouchEvent(event);
}
这个容易,invalidate嘛。抬起手指重绘嘛,那关键问题就抛给了onDraw同志。
@Override protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setAntiAlias(true);
paint.se