效果图
这Q弹的动画,妖艳的色彩转换,着实和市面上的普通Switch控件不太一样。下面对它逐一拆解,从0到1实现它。
一、设计思路
Android系统提供的SwitchButon很好地体现了metiarial design设计风格,但不够妖艳。我希望用两个比较冲突的对比色进行控件的颜色设计,这样摆在浅色背景页面的时,控件可以达到一种直刺眼睛的效果。抓人、妖艳、骚气外放。只要整体页面搭配得当,该控件必定可以“外骚内纯”。微微模糊的光晕可以使得本就亮丽的颜色变得更加妖艳。
为增加设计的可扩展性,可以改变颜色从而体现不同的风格。
二、实现方式
总体而言,虽然控件的外表非常妖艳,但交互逻辑是比较简单的。不考虑继承自系统Switch,因为并不需要再去了解如何扩展Switch。因此直接继承自View即可。整个逻辑控制在onTouchEvent中实现,声明好各个可配置的属性,如颜色、大小等等。
- UI绘制
//画背景条RectF bkgRect = new RectF((width - bkgBarW) / 2f, height / 2 - (bkgBarH / 2), (width - bkgBarW) / 2f + bkgBarW, height / 2 + (bkgBarH / 2));canvas.drawRoundRect(bkgRect, bkgBarH / 4, bkgBarH / 4, bkgBarPaint);
画前景圆角矩形:同样的,indicatorRect为待绘制圆角矩形的区域范围,indicatorW、indicatorH为指示器宽高,indicatorX、indicatorY为指示器的中心坐标点,该坐标之后会结合animator进行动态计算,最后调用canvas的drawRoundRect进行绘制
//画指示器RectF indicatorRect = new RectF( indicatorX, indicatorY, indicatorW + indicatorX, (height - indicatorH) / 2 + indicatorH);canvas.drawRoundRect(indicatorRect, indicatorH / 6, indicatorH / 6, indicatorPaint);
画图标或文字:这部分计算好文字或图标的坐标进行绘制即可,需要注意的是,如果要绘制文字,需要计算出文字的基线位置,方便与指示器在视觉上居中
//画图标int baseLineY = (int) (indicatorRect.centerY() - textTop / 2 - textBottom / 2);//基线中间点的y轴计算公式if (status == false) { canvas.drawText("♂", indicatorRect.centerX(), baseLineY, textPaint);} else { canvas.drawText("♀", indicatorRect.centerX(), baseLineY, textPaint);}
- 动画实现
animatorOn = ValueAnimator.ofFloat(indicatorStartX, indicatorEndX);animatorOn.setDuration(500);animatorOn.setInterpolator(new BounceInterpolator());animatorOn.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { indicatorX = (float) animation.getAnimatedValue(); postInvalidate(); }});animOnSet = new AnimatorSet();animOnSet.playTogether(animatorOn, animatorColorOn);animatorOff = ValueAnimator.ofFloat(indicatorEndX, indicatorStartX);animatorOff.setDuration(500);animatorOff.setInterpolator(new BounceInterpolator());animatorOff.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { indicatorX = (float) animation.getAnimatedValue(); postInvalidate(); }});animOffSet = new AnimatorSet();animOffSet.playTogether(animatorColorOff, animatorOff);
- 加亿点细节
bmShadow = BitmapFactory.decodeResource(getResources(), R.drawable.img_shadow_rect_blue);//sex_blue为配置的指示器为“开”状态时的颜色,int值bmShadow = BitmapUtils.replacePixelColor(bmShadow, sex_blue);
再仔细观察,会发现在指示器动画执行的过程中,指示器颜色也完成了一个渐变过渡。这里有个变换颜色动态计算的操作,依然采用animator进行计算,其中indicatorPaint控制指示器颜色
animatorColorOn = new ValueAnimator();animatorColorOn.setIntValues(sex_blue, sex_red);animatorColorOn.setEvaluator(new ArgbEvaluator());animatorColorOn.setDuration(500);animatorColorOn.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int color = (int) animation.getAnimatedValue(); indicatorPaint.setColor(color); }});animatorColorOff = new ValueAnimator();animatorColorOff.setIntValues(sex_red, sex_blue);animatorColorOff.setEvaluator(new ArgbEvaluator());animatorColorOff.setDuration(500);animatorColorOff.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int color = (int) animation.getAnimatedValue(); indicatorPaint.setColor(color); }});
三、后记
控件设计或开发,无处不体现着“自顶向下”的思想。弄清需求,理清逻辑,打磨细节,做到这三点,绝大部分控件设计或开发的难题一定可以迎刃而解。最后福利:学习资料赠送
- 福利:由本人亲自撰写 & 整理的「Android学习方法资料」
- 数量:10名
- 参与方式:「点击文章右下角”在看“ -> 回复截图到公众号 即可,我将从中随机抽取」点击“在看”就能升职 & 加薪水哦!