Android初级进阶之自定义View之SafeVeiw

简介: SafeView这是我模仿的一个效果,要不断的进步,就要不断的学习。主要实现的效果是一个转动的效果和一个3D触摸效果。请看效果图(录制的图片有点大):效果图知识点1. Canvas2. Paint3. Shader4. Camera(不是相机)5. Animator分析整个View看上去是有四个圆组成,内中心的圆对边上有一个小圆,圆上面还有小尾巴。

SafeView

这是我模仿的一个效果,要不断的进步,就要不断的学习。主要实现的效果是一个转动的效果和一个3D触摸效果。请看效果图(录制的图片有点大):


img_54081d55031e0cfc1186263a8e00540c.gif
效果图

知识点

1. Canvas
2. Paint
3. Shader
4. Camera(不是相机)
5. Animator

分析

整个View看上去是有四个圆组成,内中心的圆对边上有一个小圆,圆上面还有小尾巴。其实主要的原理是使用ValueAnimator来发散一个圆周的值,也就是360度,然后每次发散后旋转画布就能得到上面的效果。

技术点

  1. android.graphics.Camera是Android官方提供的3D效果组件,使用起来十分的简单,关键在于理解其中的x,y,z轴。(有空再写一篇Camera的使用)

  2. Sharder 阴影渲染

    1. 本View中主要使用了LinearGradient和RadialGradient。
      1. LinearGradient为线性渐变,在这里主要是用来画小圆的尾巴。
      2. RadialGradient为径向渐变,从圆心向外四周扩散,在这里是用来画中心圆的效果。
  3. Animator 自3.0后推出的属性动画,本文主要使用ValueAnimator。

CODE

1.初始化 && Measure

将一些全局的值在构方法中进行初始化并且测量View的宽高等。


          mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setStrokeCap(Paint.Cap.ROUND);// 圆角笔触
        mLeftLinearGradient = new LinearGradient(0, 0, mCy - OFFSET, mCy - OFFSET, 0xddffffff, 0x00000000, Shader.TileMode.CLAMP);//左边的尾巴
        mRightLinearGradient = new LinearGradient(mCy - OFFSET, mCy / 2, 0, mCy / 2, 0xddffffff, 0x00000000, Shader.TileMode.CLAMP);//右边的尾巴

2.绘制所有的背景圆

圆的颜色是从中心开始不断的淡化的,其实这只要更改透明度就可以完成这样的效果

/**
 * @param canvas
 * @param radius 直径
 * @param angle  当前角度
 */
private void canvasCircle(Canvas canvas, int radius, float angle) {
    float percentage = angle / 360f;//当前角度百分比
    mPaint.setColor(0xddffffff);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeWidth(1.5f);
    //绘制中心圆圈
    canvas.drawCircle(radius, radius, radius - OFFSET, mPaint);
    mPaint.setStyle(Paint.Style.FILL);
    mPaint.setColor(0x22ffffff);

    if (aninatopValue >= 90) {
        //绘制第二圆圈
        canvas.drawCircle(radius, radius, radius - OFFSET + 40 * percentage, mPaint);
    }
    mPaint.setColor(0x11ffffff);
    if (aninatopValue >= 180) {
        //绘制第三圆圈
        canvas.drawCircle(radius, radius, radius - OFFSET + 80 * percentage, mPaint);
    }
    if (aninatopValue >= 270) {
        //绘制第四圆圈
        canvas.drawCircle(radius, radius, radius - OFFSET + 120 * percentage, mPaint);
    }
    if (aninatopValue <= 90) {// 初始状态下绘制所有的圆圈
        mPaint.setColor(0x22ffffff);
        canvas.drawCircle(radius, radius, radius - OFFSET + 40, mPaint);
        mPaint.setColor(0x11ffffff);
        canvas.drawCircle(radius, radius, radius - OFFSET + 80, mPaint);
        canvas.drawCircle(radius, radius, radius - OFFSET + 120, mPaint);
    }
    mPaint.setColor(0xff1782dd);//绘制中心圆为背景颜色
    canvas.drawCircle(radius, radius, radius - OFFSET, mPaint);
    mPaint.setColor(0x55ffffff);
    //渲染 得到中心的 凹凸效果
    RadialGradient radialGradient = new RadialGradient(radius, radius, radius - OFFSET, new int[]{0x00000000, 0xffffffff}, null, Shader.TileMode.CLAMP);
    mPaint.setShader(radialGradient);
    canvas.drawCircle(radius, radius, radius - OFFSET, mPaint);
}

效果图:

img_f8ff2fd547909b800d19a1e260828152.png
绘制完所有的圆

3.绘制中间的文字

/**
 * //绘制文字
 *
 * @param canvas
 * @param radius
 */
private void canvasText(Canvas canvas, int radius) {
    mPaint.setShader(null);//文字颜色
    mPaint.setColor(0x88ffffff);//转换字体
    mPaint.setTextSize(DensityUtils.sp2px(getContext(), 14));
    mPaint.setStrokeWidth(2);
    mPaint.setStyle(Paint.Style.STROKE);
    String safeText = "已防御次数";
    canvas.drawText(safeText, radius - mPaint.measureText(safeText) / 2, (radius - mPaint.measureText(String.valueOf(safeText)) / 2), mPaint);
    mPaint.setStyle(Paint.Style.FILL);
    mPaint.setColor(0xffffffff);
    mPaint.setTextSize(DensityUtils.sp2px(getContext(), 30));
    mPaint.setStrokeWidth(2);
    canvas.drawText(String.valueOf(safeCount), radius - mPaint.measureText(String.valueOf(safeCount)) / 2, radius + radius / 4, mPaint);
}
img_c1d60f0f3aafccbfe3343630463ab285.png
绘制中间的文字

4.绘制左右两个圆点并旋转

到这里,基本绘制就已经完成了,只要加上角度的计算和动画部分,这个View就能够动起来了。

/**
 * 绘制旋转部分
 */
private void canvasRotate(Canvas canvas, int radius, float angle) {
    //旋转画布
    canvas.rotate(angle, radius, radius);
    //移动坐标到中心
    canvas.translate(radius, radius);
    mPaint.setShader(null);
    //左边的圆
    mPaint.setColor(Color.WHITE);
    mPaint.setStyle(Paint.Style.FILL);
    mPaint.setStrokeWidth(5);
    canvas.drawCircle(-radius + OFFSET, 0, 10, mPaint);
    //右边的圆
    canvas.drawCircle(radius - OFFSET, 0, 10, mPaint);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeWidth(8);
    //绘制坐标的圆的尾巴
    RectF mRectF = new RectF(-radius + OFFSET, -radius + OFFSET, radius - OFFSET, radius - OFFSET);
    mPaint.setShader(mRightLinearGradient);
    canvas.drawArc(mRectF, 15, 180 - 15, false, mPaint);
    mPaint.setShader(mLeftLinearGradient);
    canvas.drawArc(mRectF, 180 + 15, 180 - 15, false, mPaint);
    //合并画布
    canvas.restore();
}
img_6dd019bfaaf9022e4a22da7b12122da8.png
绘制左右两个圆点

5.动画与角度

/**
 * 开始
 */
private void startLoopAnimator() {
    //发散350度
    motionAnimator = ValueAnimator.ofFloat(360f).setDuration(1500);
    //线性差值器
    motionAnimator.setInterpolator(new LinearInterpolator());
    //永远循环
    motionAnimator.setRepeatCount(ValueAnimator.INFINITE);
    motionAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            safeCount++;
            aninatopValue = (float) animation.getAnimatedValue();
            postInvalidate();
        }
    });
    motionAnimator.start();
}
img_616687e2d9809e1c76a736692a080650.gif
加入动画后完成

最后

源码

目录
相关文章
|
1月前
|
数据可视化 Android开发 开发者
安卓应用开发中的自定义View组件
【10月更文挑战第5天】在安卓应用开发中,自定义View组件是提升用户交互体验的利器。本篇将深入探讨如何从零开始创建自定义View,包括设计理念、实现步骤以及性能优化技巧,帮助开发者打造流畅且富有创意的用户界面。
85 0
|
17天前
|
搜索推荐 前端开发 Android开发
安卓应用开发中的自定义视图实现
【10月更文挑战第30天】在安卓开发的海洋中,自定义视图是那抹不可或缺的亮色,它为应用界面的个性化和交互体验的提升提供了无限可能。本文将深入探讨如何在安卓平台创建自定义视图,并展示如何通过代码实现这一过程。我们将从基础出发,逐步引导你理解自定义视图的核心概念,然后通过一个实际的代码示例,详细讲解如何将理论应用于实践,最终实现一个美观且具有良好用户体验的自定义控件。无论你是想提高自己的开发技能,还是仅仅出于对安卓开发的兴趣,这篇文章都将为你提供价值。
|
19天前
|
Android开发 开发者 UED
安卓开发中自定义View的实现与性能优化
【10月更文挑战第28天】在安卓开发领域,自定义View是提升应用界面独特性和用户体验的重要手段。本文将深入探讨如何高效地创建和管理自定义View,以及如何通过代码和性能调优来确保流畅的交互体验。我们将一起学习自定义View的生命周期、绘图基础和事件处理,进而探索内存和布局优化技巧,最终实现既美观又高效的安卓界面。
28 5
|
26天前
|
缓存 数据处理 Android开发
在 Android 中使用 RxJava 更新 View
【10月更文挑战第20天】使用 RxJava 来更新 View 可以提供更优雅、更高效的解决方案。通过合理地运用操作符和订阅机制,我们能够轻松地处理异步数据并在主线程中进行 View 的更新。在实际应用中,需要根据具体情况进行灵活运用,并注意相关的注意事项和性能优化,以确保应用的稳定性和流畅性。可以通过不断的实践和探索,进一步掌握在 Android 中使用 RxJava 更新 View 的技巧和方法,为开发高质量的 Android 应用提供有力支持。
|
26天前
|
缓存 调度 Android开发
Android 在子线程更新 View
【10月更文挑战第21天】在 Android 开发中,虽然不能直接在子线程更新 View,但通过使用 Handler、AsyncTask 或 RxJava 等方法,可以实现子线程操作并在主线程更新 View 的目的。在实际应用中,需要根据具体情况选择合适的方法,并注意相关的注意事项和性能优化,以确保应用的稳定性和流畅性。可以通过不断的实践和探索,进一步掌握在子线程更新 View 的技巧和方法,为开发高质量的 Android 应用提供支持。
30 2
|
27天前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
|
30天前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
24 2
|
1月前
|
XML 前端开发 Java
安卓应用开发中的自定义View组件
【10月更文挑战第5天】自定义View是安卓应用开发的一块基石,它为开发者提供了无限的可能。通过掌握其原理和实现方法,可以创造出既美观又实用的用户界面。本文将引导你了解自定义View的创建过程,包括绘制技巧、事件处理以及性能优化等关键步骤。
|
1月前
|
XML 前端开发 Android开发
Android View的绘制流程和原理详细解说
Android View的绘制流程和原理详细解说
39 3
|
3月前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
View的绘制和事件处理是两个重要的主题,上一篇《图解 Android事件分发机制》已经把事件的分发机制讲得比较详细了,这一篇是针对View的绘制,View的绘制如果你有所了解,基本分为measure、layout、draw 过程,其中比较难理解就是measure过程,所以本篇文章大幅笔地分析measure过程,相对讲得比较详细,文章也比较长,如果你对View的绘制还不是很懂,对measure过程掌握得不是很深刻,那么耐心点,看完这篇文章,相信你会有所收获的。
119 3
下一篇
无影云桌面