Android水滴,小球粘性控件生成.

前幾天學了Python相關的知識,然後昨天看了一下Skype的Loading非常好看,就想要自己做一個看看.然後網上搜集了一些資料. 需要用bezier去畫圓.畫了圓後慢慢的拓展右邊的點的位置逐漸形成了圓角.

效果圖:


    需要四次貝塞爾畫一個圓,用貝塞爾畫圓需要一個因子.該因子決定了圓的程度,根據公式可以知道圓的因子:

0.551915024494f
用該因子 * 半徑 可以得到貝塞爾的起始點和終點.


    以圓爲中心,分爲四個點. 左右和上下, 這四個點就是貝塞爾的中點.

    這樣就繪製了一次貝塞爾.

mPath.moveTo(p0.x,p0.y);
mPath.cubicTo(p1.x, p1.y, p2.x, p2.y, p3.x,p3.y);


    通過上面的繪製就需要繪製四次.

    項目結構:

    

    核心代碼:

package com.softtanck.beziercircle.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.PointF;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.Transformation;

import com.softtanck.beziercircle.bean.HPoint;
import com.softtanck.beziercircle.bean.VPoint;

/**
 * @author : Tanck
 * @Description : TODO
 * @date 10/12/2015
 */
public class BezierCircle extends View {
    /** 路徑 */
    private Path mPath;
    /** 畫筆*/
    private Paint mFillCirclePaint;
    /** 四個點*/
    private VPoint p2;
    private VPoint p4;
    private HPoint p1;
    private HPoint p3;
    /** 半徑*/
    private int radius;
    private float c;
    private float blackMagic = 0.551915024494f;
    private float mInterpolatedTime;
    private float stretchDistance;

    public BezierCircle(Context context) {
        this(context, null);
    }

    public BezierCircle(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public BezierCircle(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    /**
     * 初始化操作
     */
    private void init() {
        mFillCirclePaint = new Paint();
        mFillCirclePaint.setColor(0xFFFFFFFF);//fe626d);
        mFillCirclePaint.setStyle(Paint.Style.FILL);
        mFillCirclePaint.setStrokeWidth(1);
        mFillCirclePaint.setAntiAlias(true);
        mPath = new Path();
        p2 = new VPoint();
        p4 = new VPoint();

        p1 = new HPoint();
        p3 = new HPoint();
        radius = 20;
        c = radius * blackMagic;
        stretchDistance = radius;
    }


    @Override
    protected void onDraw(Canvas canvas) {
        mPath.reset();
        canvas.translate(radius + 10, getHeight() / 2);
        if (mInterpolatedTime >= 0 && mInterpolatedTime <= 0.2) {
            CircleSpecLast(mInterpolatedTime);//圓 -> 右邊尖圓
        } else {
            updateRadius(10);
            CircleModel();
            movePosition();
            drawCircle(canvas);
            updateRadius(20);
            CircleModel();
        }
        drawCircle(canvas);
    }

    /**
     * 更新半徑
     *
     * @param r
     */
    private void updateRadius(int r) {
        radius = r;
        c = radius * blackMagic;
    }

    /**
     * 移動位置
     */
    private void movePosition() {
        float offset = (getWidth() - 3 * radius - 10) * (mInterpolatedTime - 0.2f);
        offset = offset > 0 ? offset : 0;
        offset = offset + 2 * radius + 10;
        p1.adjustAllX(offset);
        p2.adjustAllX(offset);
        p3.adjustAllX(offset);
        p4.adjustAllX(offset);
    }

    /**
     * 畫圓
     *
     * @param canvas
     */
    private void drawCircle(Canvas canvas) {
        mPath.moveTo(p1.x, p1.y);
        mPath.cubicTo(p1.right.x, p1.right.y, p2.bottom.x, p2.bottom.y, p2.x, p2.y);
        mPath.cubicTo(p2.top.x, p2.top.y, p3.right.x, p3.right.y, p3.x, p3.y);
        mPath.cubicTo(p3.left.x, p3.left.y, p4.top.x, p4.top.y, p4.x, p4.y);
        mPath.cubicTo(p4.bottom.x, p4.bottom.y, p1.left.x, p1.left.y, p1.x, p1.y);
        canvas.drawPath(mPath, mFillCirclePaint);
        mPath.reset();
    }

    private void CircleSpecLast(float time) {//0~0.2
        CircleModel();
        p2.setX(radius + stretchDistance * time * 5); // 改變最右邊的點x
    }

    private void CircleModel() {
        // p2.p4屬於圓左右兩點

        p1.setY(radius);//右邊
        p3.setY(-radius);// 左邊
        p3.x = p1.x = 0;//圓心
        p3.left.x = p1.left.x = -c;
        p3.right.x = p1.right.x = c;

        //p1.p3屬於圓的上下兩點
        p2.setX(radius); // 下邊
        p4.setX(-radius);// 上邊
        p2.y = p4.y = 0;//圓心
        p2.top.y = p4.top.y = -c;
        p2.bottom.y = p4.bottom.y = c;
    }


    /**
     * 移動動畫類
     */
    private class MoveAnimation extends Animation {

        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            super.applyTransformation(interpolatedTime, t);
            mInterpolatedTime = interpolatedTime;
            invalidate();
        }

    }

    /**
     * 開始動畫
     */
    public void startAnimation() {
        mPath.reset();
        mInterpolatedTime = 0;
        MoveAnimation move = new MoveAnimation();
        move.setDuration(3000);
        move.setInterpolator(new AccelerateDecelerateInterpolator());
        startAnimation(move);
    }
}

    github項目地址:點擊打開鏈接



參考資料:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0915/3457.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章