二十三、自定義View實現文字漸變效果(模仿今日頭條)

一、今日頭條效果

二、自定義實現效果

三、源碼實現

1、自定義View

package com.haiheng.myskindemo;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import androidx.annotation.Nullable;

public class MyTextView extends View {
    private static final String TAG = "MyTextView";
    private String text = "你好,世界";
    private Paint mPaint;
    private float percent ;

    public float getPercent() {
        return percent;
    }

    public void setPercent(float percent) {
        this.percent = percent;
        invalidate();
    }

    public MyTextView(Context context) {
        super(context);
        init();
    }

    public MyTextView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public MyTextView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        Log.e(TAG, "init: ");
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setTextSize(40);
       // mPaint.setColor(Color.parseColor("#FF0000"));
    }

    /**
     * 繪製
     *
     * @param canvas
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.e(TAG, "onDraw: " + canvas);
        //畫兩條中線
       // canvas.drawLine(0, (float) getHeight() / 2, (float) getWidth(), (float) getHeight() / 2, mPaint);
        //canvas.drawLine(getWidth() / 2, 0, getWidth() / 2, (float) getHeight(), mPaint);
        /**
         * 繪製第一層文字
         */
        drawCenterTextView(canvas);

        //再畫一層文字
        drawCenterTextView2(canvas);




    }

    private void drawCenterTextView2(Canvas canvas) {

        //保存一個畫布
        canvas.save();
        mPaint.setColor(Color.parseColor("#FF0000"));
        float height = getHeight();
        float width = getWidth();
        Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
        float ascent = fontMetrics.ascent;
        float descent = fontMetrics.descent;
        /**
         * 測量文字的寬
         */
        float textWidth = mPaint.measureText(text) ;
        /**
         * 中點的橫座標
         */
        float x = width / 2 - textWidth/2;



        /**
         * 基準線
         */
        float baseLine = height / 2 + (descent - ascent) / 2 - descent;


        //裁剪
        float left = width/2-textWidth/2;
        float top = 0;
        float right = left+textWidth*percent;


        float bottom =getHeight();

       // canvas.drawLine(left,0,left,(int)getHeight(),mPaint);

       // canvas.drawLine(right,0,right,(int)getHeight(),mPaint);

        Rect rect = new Rect((int)left,(int)top,(int)right,(int)bottom);

        canvas.clipRect(rect);
        //簡單的繪製一個文字
        canvas.drawText(text, x, baseLine, mPaint);
        canvas.restore();
    }

    /**
     * 繪製在中間
     */
    private void drawCenterTextView(Canvas canvas) {
        //保存一個畫布
        canvas.save();


        mPaint.setColor(Color.parseColor("#000000"));
        float height = getHeight();
        float width = getWidth();
        Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
        float ascent = fontMetrics.ascent;
        float descent = fontMetrics.descent;
        /**
         * 測量文字的寬
         */
        float textWidth = mPaint.measureText(text) ;
        /**
         * 中點的橫座標
         */
        float x = width / 2 - textWidth/2;
        /**
         * 基準線
         */
        float baseLine = height / 2 + (descent - ascent) / 2 - descent;


        //裁剪
        float left = (width/2-textWidth/2)+textWidth*percent;
        float top = 0;
        float right = width/2+textWidth/2;


        float bottom =getHeight();

     //   canvas.drawLine(left,0,left,(int)getHeight(),mPaint);

        //canvas.drawLine(right,0,right,(int)getHeight(),mPaint);

        Rect rect = new Rect((int)left,(int)top,(int)right,(int)bottom);

        canvas.clipRect(rect);



        //簡單的繪製一個文字
        canvas.drawText(text, x, baseLine, mPaint);
        canvas.restore();

    }


}

2、通過屬性動畫演示效果

package com.haiheng.myskindemo


import android.animation.ObjectAnimator
import android.os.Bundle
import android.os.Handler
import android.util.Log
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_text)
        val textView = findViewById<MyTextView>(R.id.myTextView)

        //屬性動畫
        val arrays = floatArrayOf(0.0f,1.0f)
        Handler().postDelayed({
            Log.e("MainActivity", "1S開啓動畫")
            ObjectAnimator.ofFloat(textView, "percent", *arrays).setDuration(4000).start()

        }, 1000)




    }
}

四、小結

  • 通過drawText實現文字繪製
  • 畫布是可以由多層組成的,通過繪製兩層文字,並通過裁剪的方式實現
  • save和restore結合使用表示保存當前一層畫布
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章