Android自定义view实现圆形waveview

最近学习了贝塞尔曲线的一些知识,刚好项目中需要实现一个圆形进度,然后就将实现的waveView记录一下。需要使用的知识大概有自定义view、贝塞尔曲线、valueAnimator(属性动画)、Xfermode等。

以下为效果图:

废话不多说,直接上代码这里只是一些重要的代码。如果需要demo可以去下载。

下载地址

首先需要自定义view的属性:

<declare-styleable name="custom_wave_view_attr">

 <attr name="circle_color" format="color"></attr> //圆的颜色
 <attr name="circle_background_color" format="color"></attr> //圆的背景色
 <attr name="progress_wave_color" format="color"></attr> //水波纹的颜色
 <attr name="progress_text_size" format="dimension"></attr> //字体的大小
 <attr name="progress_text_color" format="color"></attr>  //字体的颜色

</declare-styleable>

第二步自定义CustomWaveView

1、实现构造方法,在构造方法中获取属性值

TypedArray ta = context.obtainStyledAttributes(attrs,R.styleable.custom_wave_view_attr);
//圆的颜色
circle_color = ta.getColor(R.styleable.custom_wave_view_attr_circle_color,getResources().getColor(android.R.color.black));
//圆的背景色
circle_bg_color = ta.getColor(R.styleable.custom_wave_view_attr_circle_background_color,getResources().getColor(android.R.color.white));
//水波纹颜色
wave_color = ta.getColor(R.styleable.custom_wave_view_attr_progress_wave_color,getResources().getColor(android.R.color.holo_blue_dark));
//字体的颜色
text_color = ta.getColor(R.styleable.custom_wave_view_attr_progress_text_color,getResources().getColor(android.R.color.black));
//字体的大小
textSize = ta.getDimension(R.styleable.custom_wave_view_attr_progress_text_size,30f);
//释放资源
ta.recycle();

2、初始化画笔

//初始化背景圆画笔
mBgCirclePaint = new Paint();
//抗锯齿
mBgCirclePaint.setAntiAlias(true);
//设置背景圆的背景色
mBgCirclePaint.setColor(circle_bg_color);
//设置充满
mBgCirclePaint.setStyle(Paint.Style.FILL);
//初始化水波纹画笔
mWavePaint = new Paint();
//抗锯齿
mWavePaint.setAntiAlias(true);
//设置水波纹的背景色
mWavePaint.setColor(wave_color);
//设置充满
mWavePaint.setStyle(Paint.Style.FILL);
//使用Xfermode获取重叠部分
mWavePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));

3、绘制贝塞尔曲线。以下为原理图。

/**
* 初始化贝塞尔曲线上的点
*/
private void reset() {
 startP = new PointF(-width, height);
 nextP = new PointF(-width/2, height);
 threeP = new PointF(0, height);
 fourP = new PointF(width/2, height);
 endP = new PointF(width, height);
 controllerP1 = new PointF(-width/4, height);
 controllerP2 = new PointF(-width * 3/4, height);
 controllerP3 = new PointF(width/4, height);
 controllerP4 = new PointF(width * 3/4, height);
}

4、在onDraw方法中画贝塞尔曲线和圆

@Override
protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 //在透明画布上画背景圆
 mCanvas.drawCircle(width/2, height/2, radius, mBgCirclePaint);
 //贝塞尔曲线
 mPath.reset();
 mPath.moveTo(startP.x, startP.y);
 mPath.quadTo(controllerP1.x, controllerP1.y, nextP.x, nextP.y);
 mPath.quadTo(controllerP2.x, controllerP2.y, threeP.x, threeP.y);
 mPath.quadTo(controllerP3.x, controllerP3.y, fourP.x, fourP.y);
 mPath.quadTo(controllerP4.x, controllerP4.y, endP.x, endP.y);
 mPath.lineTo(endP.x, height);
 mPath.lineTo(-width, height);
 //在透明画布上绘制水波纹
 mCanvas.drawPath(mPath,mWavePaint);
 //将画好的圆绘制在画布上
 canvas.drawBitmap(mBitmap, 0, 0, null);
}

5、使用动画让贝塞尔曲线动起来

/**
* 开始动画 让startP的x点坐标在2S时间内循环移动到0点。
* depth---进度
* waveRipple----水波纹的振幅
*/
private void startAnimator() {
 animator = ValueAnimator.ofFloat(startP.x, 0);
 animator.setInterpolator(new LinearInterpolator());
 animator.setDuration(2000);
 //重复循环
 animator.setRepeatCount(ValueAnimator.INFINITE);
 animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
 @Override
 public void onAnimationUpdate(ValueAnimator animation) {
 startP.x = (Float) animation.getAnimatedValue();
 startP = new PointF(startP.x, height - depth);
 nextP = new PointF(startP.x + width/2, height - depth);
 threeP = new PointF(nextP.x + width/2, height - depth);
 fourP = new PointF(threeP.x + width/2, height - depth);
 endP = new PointF(fourP.x + width/2, height - depth);
 controllerP1 = new PointF(startP.x + width/4, height - depth + waveRipple);
 controllerP2 = new PointF(nextP.x + width/4, height - depth - waveRipple);
 controllerP3 = new PointF(threeP.x + width/4, height - depth + waveRipple);
 controllerP4 = new PointF(fourP.x + width/4, height - depth - waveRipple);
 invalidate();
 }
 });
 animator.start();
}

第三步在XML中使用自定义View

<com.criclewaveview_master.CustomWaveView
 android:id="@+id/custom_circle_wave_view"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 wave:circle_color = "@color/circle_color"
 android:layout_centerInParent="true"
 wave:circle_background_color = "@color/circle_bg_color"
 wave:progress_wave_color = "@color/colorAccent"
 wave:progress_text_size = "20sp"
 wave:progress_text_color = "@color/circle_color"/>

这样就完成了自定义WaveView。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android贝塞尔曲线实现消息拖拽消失

    写在前头 写消息拖拽效果的文章不少,但是大部分都把自定义View写死了,我们要实现的是传入一个View,每个View都可以实现拖拽消失爆炸的效果,当然我也是站在巨人的肩膀上来学习的.但个人觉得程序员本就应该敢于学习和借鉴. 源码地址:源码Github地址 效果图 分析(用到的知识点):  (1)ValueAnimator (数值生成器) 用于生成数值,可以设置差值器来改变数字的变化幅度. (2)ObjectAnimator (动画生成器) 用于生成各种属性,布局动画,同样也可以设置差值器来改变效

  • Android贝塞尔曲线初步学习第一课

    贝塞尔曲线有一阶.二阶.三阶.N阶 一阶就是一条直线,有起点终点,没有控制点,对应方法就是 canvas.drawLine(float startX, float startY, float stopX, float stopY, @NonNull Paint paint) ; 二阶为曲线,有起点终点,一个控制点,对应方法就是 path.quadTo(float x1, float y1, float x2, float y2); 其中x1.y1为控制点坐标, x2.y2为终点坐标,效果如下:

  • Android贝塞尔曲线初步学习第三课 Android实现添加至购物车的运动轨迹

    不知上一节高仿QQ未读消息气泡大家还喜欢么,今天继续练习贝赛尔曲线,这一节我们通过贝赛尔曲线和属性动画估值器实现添加至购物车的运动轨迹,效果如下: 1.新建自定义View,重写构造方法,初始化Paint.Path: 2.确定起始点.终止点.控制点坐标,这里我们直接固定: @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh);

  • Android利用二阶贝塞尔曲线实现添加购物车动画详解

    一.引入 其实之前一直以为像饿了么或者是美团外卖那种把商品添加到购物车的动画会很难做,但是实际做起来好像并没有想象中的那么难哈哈. 布局主要使用CoordinatorLayout+AppBarLayout+CollapsingToolbarLayout+TabLayout+ViewPager 动画主要使用二阶贝塞尔曲线与属性动画 消息传递使用EventBus普通事件 二.大致思路 1.如图所示主要有三个点,起点.终点.以及贝塞尔曲线的控制点 2.起点即点击的View的位置,一般来说用如下方式即可

  • Android贝塞尔曲线实现填充不规则图形并随手指运动

    贝塞尔曲线: 贝塞尔曲线于1962,由法国工程师皮埃尔·贝塞尔所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计.贝塞尔曲线最初由 Paul de Casteljau 于 1959 年运用 de Casteljau 演算法开发,以稳定数值的方法求出贝兹曲线.贝塞尔曲线主要用于二维图形应用程序中的数学曲线,曲线由起始点,终止点(也称锚点)和控制点组成,通过调整控制点,贝塞尔曲线的形状会发生变化. 在此举一个例子,实现贝塞尔曲线,基于以下场景: 上面的图片,我们可以见到一个白色的区域,边缘为弧形,这

  • Android贝塞尔曲线实现直播点赞效果

    本文实例为大家分享了Android实现直播点赞效果的具体代码,供大家参考,具体内容如下 效果展示 原理分析 点赞效果最主要的难点和原理在于贝塞尔曲线动画的生成,我们通过图片主要讲解贝塞尔曲线动画 1.需要找到贝塞尔曲线的四个点 2.通过三级贝塞尔曲线的公式计算,获取贝塞尔曲线的轨迹路径点 3.通过设置点赞图片X,Y坐标,从而形成点赞的效果 实现步骤 1.初始化变量 //1.继承RelativeLayout public class ChristmasView extends RelativeLa

  • Android使用贝塞尔曲线仿QQ聊天消息气泡拖拽效果

    本文实例为大家分享了Android仿QQ聊天消息气泡拖拽效果展示的具体代码,供大家参考,具体内容如下 先画圆,都会吧.代码如下: public class Bezier extends View { private final Paint mGesturePaint = new Paint(); private final Path mPath = new Path(); private float mX1 = 100, mY1 = 150; private float mX2 = 300, m

  • Android 利用三阶贝塞尔曲线绘制运动轨迹的示例

    本篇文章主要介绍了Android 利用三阶贝塞尔曲线绘制运动轨迹的示例,分享给大家,具体如下: 实现点赞效果,自定义起始点以及运动轨迹 效果图: xml布局: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/rl_root&

  • Android仿百度地图小度语音助手的贝塞尔曲线动画

    本文为大家分享了Android仿小度语音助手的贝塞尔曲线动画,供大家参考,具体内容如下 废话不多说,看下面的动图,和百度的还是有点点差别,我也不修改了,很简单,我实在是没有多余的时间,还要学习其他的东西. package com.example.helang.volumewave; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Canvas; impo

  • Android Path绘制贝塞尔曲线实现QQ拖拽泡泡

    这两天学习了使用Path绘制贝塞尔曲线相关,然后自己动手做了一个类似QQ未读消息可拖拽的小气泡,效果图如下: 最终效果图 接下来一步一步的实现整个过程. 基本原理 其实就是使用Path绘制三点的二次方贝塞尔曲线来完成那个妖娆的曲线的.然后根据触摸点不断绘制对应的圆形,根据距离的改变改变原始固定圆形的半径大小.最后就是松手后返回或者爆裂的实现. Path介绍: 顾名思义,就是一个路径的意思,Path里面有很多的方法,本次设计主要用到的相关方法有 moveTo() 移动Path到一个指定的点 qua

随机推荐