一、今日頭條效果
二、自定義實現效果
三、源碼實現
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結合使用表示保存當前一層畫布