canvas教程

Android自定义控件水波加速球

字号+ 作者:H5之家 来源:H5之家 2017-04-26 17:00 我要评论( )

Android自定义控件水波加速球

itdadao


通过上一篇的博客,相信你对Android中的坐标系和绘制刻度的实现原理有了一个认识(所以这一篇可能没有那么详细。。。),接下来就是另外一部分内容,如何去绘制水波加速球。

自定义View确定一个正方形 public class WaterView extends View { private int len; public WaterView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); //以最小值为正方形的长 len = Math.min(width, height); //设置测量高度和宽度(必须要调用,不然无效果) setMeasuredDimension(len, len); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); } }

同样这里集成了View,并通过设置测量值,限定空间为正方形。
布局中使用:

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/ll_parent" android:orientation="vertical" android:background="@color/colorPrimary" android:padding="20dp" tools:context="com.example.huaweiview.MainActivity"> <com.example.huaweiview.WaterView android:layout_gravity="center" android:background="@color/colorAccent" android:layout_width="200dp" android:layout_height="300dp" /> </LinearLayout>

itdadao


ok,我们设置的长度和宽度并不一样,但是他显示的是一个正方形,并且,根据上一篇博客的介绍,它是有自己的坐标系的,我们绘制的所有东西都在这个坐标系内,并且依靠它去确定位置。

回忆正余弦

大家通过查资料和联想心电图等可以知道,水波其实就是在绘制一条正弦或者余弦波,如果让这条波移动就是

itdadao


这里我们使用正弦实现需要如下公式:
y = Asin(wx+b)+h ,这个公式里:w影响周期,A影响振幅,h影响y位置,b为初相;
画图就少不了要确定不同的点,通过这个公式,我们可以得到Y轴坐标点的值,那么X轴坐标点的值该如何得到呢?
通过观察图我们可以发现,这些点连起来就是一条曲线,也就是说每个点之间的距离是非常小的,是不是可以用,这些所有的点都在X轴上有值,刚好是i(i从0加到len的长度(View的长度也就是圆的直径))

itdadao


比如图中的中间点的坐标(y=0,x=i=len/2)
当然Y值是通过公式得到的,既然有很多点,我们就需要用数组来保存这些点,水波效果最好是有两条效果会好些,所以需要个数组:

@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int width = MeasureSpec.getSize(widthMeasureSpec); int height = MeasureSpec.getSize(heightMeasureSpec); //以最小值为正方形的长 len = Math.min(width, height); //定义两个数组,保存Y值 firstWaterLine = new float[len]; secondWaterLine = new float[len]; //设置测量高度和宽度(必须要调用,不然无效果) setMeasuredDimension(len, len); }

这里定义了两个全局数组,用来保存Y轴值,个数和View长度相等(直径相等)
然后就是利用公式获取每个点的Y轴坐标值

@Override protected void onDraw(Canvas canvas) { // y = Asin(wx+b)+h ,这个公式里:w影响周期,A影响振幅,h影响y位置,b为初相; // 将周期定为view总宽度 float mCycleFactorW = (float) (2 * Math.PI / len); // 得到第一条波的y值 for (int i = 0; i < len; i++) { firstWaterLine[i] = (float) (10 * Math .sin(mCycleFactorW * i)); } // 得到第二条波的y值(第二条波的初相偏左) for (int i = 0; i < len; i++) { secondWaterLine[i] = (float) (15 * Math.sin(mCycleFactorW * i + 10)); } }

在onDraw()方法中分别得到了两个数组中Y轴的值,并且将他一个周期的长度定位len(和直径相等)每个值都对应着一个X轴的值,也就是说我们得到两个正弦波上的所有点的坐标值了。并且第二天波偏左一点
而且还要增加一下他们的振幅,不然0-1之间的值太小,显示在屏幕上像一条直线。

itdadao


上图是什么意思呢?我们的水波效果是下面有填充色的,那么这些填充色其实就是波上的每个点,往View的底边画的一条一条的直线(数学中的细分法或者微积分吧)然后线就组成了面。
ok,划线需要知道起点坐标,和终点坐标,如图中的两个绿色的坐标点。(i,y)到(i,len);接下来开始画直线

public WaterView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); waterPaint = new Paint(); //抗锯齿 waterPaint.setAntiAlias(true); waterPaint.setColor(Color.GREEN); } @Override protected void onDraw(Canvas canvas) { // y = Asin(wx+b)+h ,这个公式里:w影响周期,A影响振幅,h影响y位置,b为初相; // 将周期定为view总宽度 float mCycleFactorW = (float) (2 * Math.PI / len); // 得到第一条波的y值 for (int i = 0; i < len; i++) { firstWaterLine[i] = (float) (10 * Math .sin(mCycleFactorW * i)); } // 得到第二条波的y值 for (int i = 0; i < len; i++) { secondWaterLine[i] = (float) (15 * Math.sin(mCycleFactorW * i + 10)); } //第一条波的所有直线 for (int i = 0; i < len; i++) { canvas.drawLine(i, firstWaterLine[i], i, len, waterPaint); } //第二条波的所有直线 for (int i = 0; i < len; i++) { canvas.drawLine(i, secondWaterLine[i], i, len, waterPaint); } }

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • android自定义组件(手机加速球+水面波动效果)

    android自定义组件(手机加速球+水面波动效果)

    2017-04-26 12:03

  • Android多屏幕适配

    Android多屏幕适配

    2017-04-25 11:02

  • Android图形图像之自定义控件属性(demo:刮刮乐与打

    Android图形图像之自定义控件属性(demo:刮刮乐与打

    2017-04-24 13:01

  • Class:android总类/android覆盖物类

    Class:android总类/android覆盖物类

    2017-04-20 08:00

网友点评
p