1. 程式人生 > >Android TextView文字鏤空效果的兩種實現

Android TextView文字鏤空效果的兩種實現

一圖勝千言

文字鏤空效果主要有兩種實現方式:

1,自動義View,在canvas中繪製圓角矩形作為背景,然後繪製文字,通過PorterDuff.Mode.DST_OUT把背景擦除,實現鏤空效果。如上圖中的第一個。

2,自定義TextView,定義兩Bitmap,分別在Bitmap上畫背景和文字前景,然後通過PorterDuff.Mode.DST_OUT,把背景擦除,實現鏤空效果。如上圖中的第二個。

比較:兩種方式原理上是一樣的,但是第二種方式繼承自TextView,可以直接使用TextView的屬性,如字型大小、顏色、樣式等等。而第一種則需要定義大量的屬性。

下面分別介紹兩種方式。

一,自動義View方式。

1,初始化

public void init(Context context, AttributeSet attrs) {
    if (attrs != null) {
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.HollowView);
        // 獲取要實現的內容
        textString = a.getString(R.styleable.HollowView_textString);
        // 獲取背景色
        mBgColor = a.getColor(R.styleable.HollowView_bgColor, mBgColor);
        if (a.hasValue(R.styleable.HollowView_textSize)) {
            // 獲取文字大小
            textSize = a.getDimension(R.styleable.HollowView_textSize, textSize);
        }
        // 獲取圓角半徑
        mRadius=a.getDimension(R.styleable.HollowView_radius,mRadius);
        a.recycle();
    }
​
    mPaint = new Paint();
    mPaint.setTextSize(textSize);
    mPaint.setAntiAlias(true);
    mPaint.setColor(mBgColor);
    
    Paint.FontMetrics fontMetrics = mPaint.getFontMetrics();
    // 計算繪製文字起始點的Y值
    drawY = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
}

2,測量

這裡用了預設的wrap_content測量方式,如果有需要可自行修改。

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    // 獲取文字寬度
    width = FontUtil.getTextWidth(textString, mPaint);
    // 獲取文字高度
    height = FontUtil.getTextHeight(textString, mPaint);
    // 計算空間應占的寬度
    mWidth = width + getPaddingLeft() + getPaddingRight();
    // 計算空間應占的高度
    mHeight = height + getPaddingTop() + getPaddingBottom();
    // 背景的繪製範圍
    rectF = new RectF(-mWidth / 2, -mHeight / 2, mWidth / 2, mHeight / 2);
​
    setMeasuredDimension(mWidth, mHeight);
}

3,繪製

protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    // 移動原點到view中心
    canvas.translate(mWidth / 2, mHeight / 2);
    // 儲存layer
    int layer = canvas.saveLayer(rectF, mPaint);
    // 繪製圓角矩形的背景
    canvas.drawRoundRect(rectF, mRadius, mRadius, mPaint);
    // 設定畫筆PorterDuff.Mode.DST_OUT模式
    mPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
    // 繪製文字
    canvas.drawText(textString, -width / 2, drawY, mPaint);
    mPaint.setXfermode(null);
    // 還原圖層
    canvas.restoreToCount(layer);
}

這樣就實現了圖中第一個效果。

4,使用

<per.wangsj.myview.view.textview.HollowView
        android:id="@+id/hollowView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:textString="撒拉嘿!"
        app:bgColor="@color/color_1"
        app:textSize="24sp"
        app:radius="4dp"
        android:paddingLeft="8dp"
        android:paddingRight="8dp"
        android:paddingTop="4dp"
        android:paddingBottom="4dp"
        />

二,自動義TextView方式。

1,初始化屬性,畫筆等

private void init(AttributeSet attrs) {
    TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.HollowView);
    // 獲取背景顏色屬性
    bgColor = typedArray.getColor(R.styleable.HollowView_bgColor, bgColor);
    // 獲取圓角半徑屬性
    mRadius = typedArray.getDimension(R.styleable.HollowView_radius, mRadius);
    // 獲取文字
    textString = getText().toString();
    // 初始化畫筆
    bgPaint = new Paint();
    bgPaint.setColor(bgColor);
    bgPaint.setAntiAlias(true);
}

2,初始化兩個Bitmap和canvas

通過canvas分別在bitmap上繪製文字,和背景。

private void initCanvas() {
    // 顯示文字的Bitmap
    textBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_4444);
    textCanvas = new Canvas(textBitmap);
    // 計算文字開始繪製位置的Y值
    Paint.FontMetrics fontMetrics = getPaint().getFontMetrics();
    float y = mHeight / 2 + (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
    
    // 在textBitmap上畫背景
    textCanvas.drawText(textString, getPaddingLeft(), y, getPaint());
​
    // 繪製背景的bitmap
    bgBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_4444);
    Canvas bgCanvas = new Canvas(bgBitmap);
    // 在bgBitmap上畫背景
    bgCanvas.drawRoundRect(0, 0, mWidth, mHeight, mRadius, mRadius, bgPaint);
}

3,繪製

protected void onDraw(Canvas canvas) {
    // 儲存圖層
    int layer = canvas.saveLayer(0, 0, mWidth, mHeight, bgPaint);
    // 畫背景 
    canvas.drawBitmap(bgBitmap, 0, 0, bgPaint);
    // 設定畫筆模式
    bgPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT));
    // 畫文字
    canvas.drawBitmap(textBitmap, 0, 0, bgPaint);
    bgPaint.setXfermode(null);
    // 還原圖層
    canvas.restoreToCount(layer);
}

程式碼註釋已經比較清楚了,就不多做解釋了。

可以看出,這種方式只需要新增背景色和圓角半徑兩個自定義屬性。

4,使用

<per.wangsj.myview.view.textview.HollowTextView
        android:id="@+id/hollowTextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="24sp"
        android:paddingLeft="8dp"
        android:paddingRight="8dp"
        app:bgColor="@color/color_1"
        app:radius="4dp"
        android:text="撒拉嘿!"/>

 

 

參考:https://www.colabug.com/4763345.html