技術共享之貝塞爾曲線

貝塞爾曲線的應用場景 : 文件下載的進度 、 充電電量的上升進度、水波紋效果
效果圖 :

自定義控件 新建一個類 Wave 繼承view

package besia.test.liang.com.besiacom.liang.test.besia;

import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.LinearInterpolator;

/**
 * Created by 樑 on 2017/12/14.
 */

public class Wave extends View {

    private Paint paint;
    private Path path;
    private int waveLength = 300;  //波長的寬度
    private int dx;
    private int dy;

    public Wave(Context context, AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint();
        paint.setColor(Color.RED);
        paint.setStyle(Paint.Style.FILL_AND_STROKE);

        path = new Path();

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        path.reset();  //重置 path
        int originY = getHeight();
        if(dy<originY + 150){
            dy += 10;  //高度每秒 + 10
        }
        int halfWaveLength = waveLength/2;   //半個波長
        path.moveTo(-waveLength+dx, originY-dy);
        //屏幕的寬度裏面放多少個波長
        for (int i = -waveLength; i < getWidth() + waveLength; i += waveLength) {
            //相對繪製二階貝塞爾曲線(相對於自己的起始點--也即是上一個曲線的終點  的距離dx1)
            path.rQuadTo(halfWaveLength/2, -80, halfWaveLength, 0);
            path.rQuadTo(halfWaveLength/2, 80, halfWaveLength, 0);
//          path.quadTo(x1, y1, x2, y2)

        }
        //顏色填充
        //畫一個封閉的空間
        path.lineTo(getWidth(), getHeight());
        path.lineTo(0, getHeight());
        path.close();

        canvas.drawPath(path, paint);  //開始繪製
    }

    public void startAnimation(){
        ValueAnimator animator = ValueAnimator.ofInt(0,waveLength);
        animator.setDuration(1000);  //設置時長
        animator.setInterpolator(new LinearInterpolator());  //設置線性加速器
        //無限循環
        animator.setRepeatCount(ValueAnimator.INFINITE);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {

            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                dx = (int) animation.getAnimatedValue();
                postInvalidate();  //重繪
            }
        });
        animator.start();
    }
}

在佈局(activity_main)中使用 該控件

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    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"
    tools:context="besia.test.liang.com.besiacom.liang.test.besia.MainActivity">

    <besia.test.liang.com.besiacom.liang.test.besia.Wave
        android:id="@+id/wave"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</android.support.constraint.ConstraintLayout>

在MainActivity中讓控件動起來

package besia.test.liang.com.besiacom.liang.test.besia;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.view.View;

/**
 * Created by 樑 on 2017/12/14.
 */

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Wave wave = (Wave)findViewById(R.id.wave);
        wave.startAnimation();
    }
}

以上是簡單實現波浪的效果 ,如果想用到項目中,例如進度,自定義屬性就行了,以下 不再提供代碼

發佈了27 篇原創文章 · 獲贊 12 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章