Android开发大前端开发

手把手教你实现一个丝滑般的控件Q弹效果(滑动+Q弹+渐变)

2020-11-20  本文已影响0人  程序媛饭冰冰

前言

很多人觉得Android的用户体验没有iOS好,但是近年来,随着众多Android开发者的努力,现在的Android已经有着不输于iOS的实力,用户体验也在直线上升。

今天要和大家分享的是一个丝滑般的控件Q弹效果,希望对大家的学习和工作有所启发和帮助。

废话就不多说了,直接上效果图,让你感受一下到底有多丝滑,又有多Q弹。

这Q弹的动画,妖艳的色彩转换,着实和市面上的普通Switch控件不太一样。下面对它逐一拆解,从0到1实现它。

设计思路

Android系统提供的SwitchButon很好地体现了metiarial design设计风格,但不够妖艳。我希望用两个比较冲突的对比色进行控件的颜色设计,这样摆在浅色背景页面的时,控件可以达到一种直刺眼睛的效果。抓人、妖艳、骚气外放。只要整体页面搭配得当,该控件必定可以“外骚内纯”。微微模糊的光晕可以使得本就亮丽的颜色变得更加妖艳。

为增加设计的可扩展性,可以通过改变颜色从而达到体现不同风格的目的。

image

实现方式

总体而言,虽然控件的外表非常妖艳,但交互逻辑是比较简单的。不考虑继承自系统Switch,因为并不需要再去了解如何扩展Switch。因此直接继承自View即可。整个逻辑控制在onTouchEvent中实现,声明好各个可配置的属性,如颜色、大小等等。

UI绘制

可以看到,图形由两大部分构成,一个是前面蓝色的圆角矩形(指示器),一个是后面红色的长条矩形(背景条),分别对这两个图形进行绘制即可。onDraw部分的代码如下:

//画背景条
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);
//画指示器
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的学习是一条漫长的道路,每个地方都是值得学习的内容。

其中,控件设计或开发这个点就无处不体现着“自顶向下”的思想。在实际工作中,我们会遇到各种各样的需求,但是不要慌!只要我们静下心来,弄清需求,理清逻辑,打磨细节,做到这三点,绝大部分控件设计或开发的难题都可以迎刃而解。

我把自己这段时间整理的Android最重要最热门的学习方向资料放在了我的GitHub:https://github.com/xieyuliang/Android-P7-share/blob/master/Android,里面还有不同方向的自学编程路线、面试题集合/面经、及系列技术文章等。

资源持续更新中,欢迎大家一起学习和探讨

上一篇 下一篇

猜你喜欢

热点阅读