二十三、自定义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结合使用表示保存当前一层画布
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章