Android View 仿iOS SwitchButton [Material Design]

本文介绍了如何在 Android 中实现一个仿iOS样式的SwitchButton,通过纯代码实现背景、按钮和阴影效果。作者分享了分析过程和实现步骤,包括自定义View的绘制方法、点击事件处理、动画效果的添加,以及状态管理和接口设计,提供了一个完整的仿iOS SwitchButton 控件实现。
摘要由CSDN通过智能技术生成

尊重原创转载请注明: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
评论 65
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值