圓環形TextView+旋轉動畫

效果圖

備註:效果是四個自定義的CircleTextView設置不同的旋轉方向、速度、透明度居中對齊的最終效果。

旋轉TextView

實現原理:

1、繪製圓環形路徑TextView
private void drawCircleText(Canvas canvas) {

    Path path = new Path();
    path.addCircle(centerX, centerY, radius, Path.Direction.CW);
    canvas.drawTextOnPath(getText().toString(), path, 0, 0, paint);
}
2、設置rotation屬性動畫
public void doAnimation() {

    if (rotationCM)
        animator = ObjectAnimator.ofFloat(this, "rotation", 0f, 360f);
    else
        animator = ObjectAnimator.ofFloat(this, "rotation", 360f, 0f);

    animator.setDuration(rotationTime);
    animator.setRepeatMode(ValueAnimator.RESTART);
    animator.setRepeatCount(ValueAnimator.INFINITE);
    animator.setInterpolator(new LinearInterpolator());
    animator.start();
}
3、備註:自定義的xml屬性,諸如:旋轉方向、文字透明度、旋轉一圈用時…請見詳細代碼

詳細代碼

1、自定義CircleTextView代碼
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Shader;
import android.graphics.SweepGradient;
import android.text.Layout;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.animation.LinearInterpolator;
import android.widget.TextView;

import com.example.zpf.animmenu.R;

/**
 * Created by zpf on 2016/11/9.
 * 圓形路徑旋轉文字
 */
public class CircleTextView extends TextView {


    /**
     * 默認文字透明度
     */
    private final int DEFAULT_ALPHA = 120;

    /**
     * 默認的旋轉一週的時間
     */
    private final int DEFAULT_ROTATION_TIME = 4000;
    /**
     * 文字旋轉中心點座標
     */
    private float centerX, centerY;

    /**
     * 根據控件長寬測量的半徑
     */
    private float radius;

    /**
     * 文字畫筆
     */
    private TextPaint paint;

    /**
     * text alpha
     */
    private int alpha = DEFAULT_ALPHA;

    /**
     * 是否順時針旋轉(默認逆時針)
     */
    private boolean rotationCM = false;

    /**
     * 旋轉一圈的時間
     */
    private int rotationTime = DEFAULT_ROTATION_TIME;

    private ObjectAnimator animator;

    public CircleTextView(Context context) {
        super(context);
    }

    public CircleTextView(Context context, AttributeSet attrs) {
        super(context, attrs);

        initDefineAttr(context, attrs);
        initPaint();
    }

    public CircleTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        initDefineAttr(context, attrs);
        initPaint();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {

        radius = Math.min(w, h) / 2 - getTextSize();
        centerX = w / 2;
        centerY = h / 2;

        super.onSizeChanged(w, h, oldw, oldh);
    }

    private void initDefineAttr(Context context, AttributeSet attrs) {

        TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CircleTextView);
        int count = array.getIndexCount();

        for (int i = 0; i < count; i++) {

            int attr = array.getIndex(i);

            switch (attr) {

                case R.styleable.CircleTextView_circleTextAlpha:

                    alpha = array.getInt(attr, DEFAULT_ALPHA);
                    if (alpha < 0 || alpha > 255)
                        alpha = DEFAULT_ALPHA;
                    break;

                case R.styleable.CircleTextView_circleRotationCW:

                    rotationCM = array.getBoolean(attr, false);
                    break;

                case R.styleable.CircleTextView_circleRotationTime:

                    rotationTime = array.getInt(attr, DEFAULT_ROTATION_TIME);
                    break;

                default:
                    break;
            }
        }

        array.recycle();
    }

    /**
     * init Paint
     */
    private void initPaint() {

        paint = new TextPaint();
        paint.setAntiAlias(true);
        paint.setColor(getCurrentTextColor());
        paint.setStyle(Paint.Style.FILL);
        paint.setTextSize(getTextSize());
        paint.setAlpha(alpha);

        //文本漸變
//        float textWidth = paint.measureText(getText().toString());
//        Shader shader = new LinearGradient(0, 0, textWidth, 0, Color.TRANSPARENT,
//                getCurrentTextColor(), Shader.TileMode.CLAMP);
//        paint.setShader(shader);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        drawCircleText(canvas);
    }

    /**
     * draw circle text
     */
    private void drawCircleText(Canvas canvas) {

        Path path = new Path();
        path.addCircle(centerX, centerY, radius, Path.Direction.CW);
        canvas.drawTextOnPath(getText().toString(), path, 0, 0, paint);
    }

    public void doAnimation() {

        if (rotationCM)
            animator = ObjectAnimator.ofFloat(this, "rotation", 0f, 360f);
        else
            animator = ObjectAnimator.ofFloat(this, "rotation", 360f, 0f);

        animator.setDuration(rotationTime);
        animator.setRepeatMode(ValueAnimator.RESTART);
        animator.setRepeatCount(ValueAnimator.INFINITE);
        animator.setInterpolator(new LinearInterpolator());
        animator.start();
    }

    public void cancelAnimation() {

        animator.cancel();
    }
}
2、用到的自定義屬性的attrs.xml內部的樣式表declare-styleable聲明
<!-- CircleTextView -->
    <declare-styleable name="CircleTextView">
        <!-- 文本透明度(0-255,數值越小越透明) -->
        <attr name="circleTextAlpha" format="integer" />

        <!-- 順時針旋轉文字 -->
        <attr name="circleRotationCW" format="boolean" />

        <!-- 旋轉文字一圈的時間(毫秒) -->
        <attr name="circleRotationTime" format="integer" />
    </declare-styleable>
3、xml佈局文件當中引用
<customview.CircleTextView
                android:id="@+id/ctv_one"
                android:layout_centerInParent="true"
                android:layout_width="80dp"
                android:layout_height="80dp"
                android:text="殷疑曙霞染,巧類匣刀裁"
                android:textColor="@color/colorWhite"
                android:textSize="12sp"
                app:circleTextAlpha="60"
                app:circleRotationCW="true"
                app:circleRotationTime="4000"/>

備註:
a、app:circleTextAlpha=“integer”爲文字透明度,取值[0-255]
b、app:circleRotationCW=”boolean” 爲是否爲順時針旋轉
c、app:circleRotationTime=“long”爲旋轉一週用時,單位毫秒

4、activity中啓動動畫使用
//啓動動畫:調用CircleTextView的
doAnimation();

//取消動畫:調用CircleTextView的
CircleTextView.cancelAnimation();
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章