自定義View基礎實戰--文字居中、圖文混排

實戰view四:文字居中

當我們在使用canvas.drawText時,它的參數有文字偏移的座標設置,要設置好偏移座標需要理解text文字繪製的幾條baseline的線,如果不設置則,文字會稍稍偏上,如左圖,設置好偏移後效果如右圖相關參考https://hencoder.com/ui-1-3/

            

 

package com.test.drawing.view;

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.view.View;

import com.test.drawing.Utils;

import androidx.annotation.Nullable;

public class SportsView extends View {

    private static final float RING_WIDTH = Utils.dp2px(20);
    private static final float RADIUS = Utils.dp2px(150);
    private static final int CIRCLE_COLOR = Color.parseColor("#90A4AE");
    private static final int HIGHLIGHT_COLOR = Color.parseColor("#FF4081");

    Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);

    Rect rect = new Rect();

    Paint.FontMetrics fontMetrics = new Paint.FontMetrics();

    public SportsView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        paint.setTextSize(Utils.dp2px(80));
        paint.getFontMetrics(fontMetrics);
        paint.setTextAlign(Paint.Align.CENTER);

    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // 繪製環
        paint.setStyle(Paint.Style.STROKE);
        paint.setColor(CIRCLE_COLOR);
        paint.setStrokeWidth(RING_WIDTH);
        canvas.drawCircle(getWidth() / 2, getHeight() / 2, RADIUS, paint);

        // 繪製進度條
        paint.setColor(HIGHLIGHT_COLOR);
        paint.setStrokeCap(Paint.Cap.ROUND);
        canvas.drawArc(getWidth() / 2 - RADIUS, getHeight() / 2 - RADIUS,
                getWidth() / 2 + RADIUS, getHeight() / 2 + RADIUS,
                -90, 225, false, paint);

        paint.setTextSize(Utils.dp2px(100));
        paint.setStyle(Paint.Style.FILL);
        paint.setTextAlign(Paint.Align.CENTER);
        //offset修正text的位置
        //修正方式一:
        paint.getTextBounds("abab", 0, "abab".length(), rect);
        float offset1 = (rect.top + rect.bottom) / 2;
        //修正方式二:
        float offset = (fontMetrics.ascent + fontMetrics.descent) / 2;
        canvas.drawText("abab", getWidth() / 2, getHeight() / 2 - offset, paint);
    }
}

如上,有兩種修正方式:

方式一:計算好這個textview的bounds的上下值,相加後/2,就是需要再偏移回來的值

//修正方式一:
        paint.getTextBounds("abab", 0, "abab".length(), rect);
        float offset1 = (rect.top + rect.bottom) / 2;

方式二:使用Paint.FontMetrics,

Paint.FontMetrics fontMetrics = new Paint.FontMetrics();
paint.getFontMetrics(fontMetrics);
float offset = (fontMetrics.ascent + fontMetrics.descent) / 2;

 

實戰view五:圖文混排,文字可以自動折行

package com.test.drawing.view;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;

import com.test.drawing.R;
import com.test.drawing.Utils;

import androidx.annotation.Nullable;

public class ImageTextView extends View {
    private static final float IMAGE_WIDTH = Utils.dp2px(100);
    private static final float IMAGE_OFFSET = Utils.dp2px(80);

    Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
    Bitmap bitmap;
    Paint.FontMetrics fontMetrics = new Paint.FontMetrics();
    String text = "按照泰戈爾《流螢集》的說法,你不應該去追尋或者試圖證明自己的存在,因爲你原本就存在,你也不應該去追尋或者試圖證明自己存在的意義,因爲你存在的本身就是意義,如同流螢、如同星空,如同草長鶯飛,四時消長的萬物,人也只是自然的一部分,你只是按照規律繁衍與更替。但是對於我來說,我沒法被這樣的環狀邏輯所說服。在我看來,人生並沒有什麼意義,活着也並沒有什麼意義,沒有意義就是沒有意義,後面不用跟上一個轉折,在沒有意義的前提下再次賦予意義。意義這種東西,由於可以被賦予,所以因人而異,這個世界上到處存在着這樣的事情,某些人覺得毫無意義,另一些人覺得意義非凡。如果在同一件事情上,意義的尺度可以被拉成無限小至無限大,而且任意的兩個尺度之間不存在證僞的可能性和必要,那麼,意義其實並沒有什麼價值。換一種說法就是,意義本身並沒有什麼意義,它並非是萬物自帶的固有屬性。";
    float[] cutWidth = new float[1];

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

    {
        bitmap = getAvatar((int) Utils.dp2px(100));
        paint.setTextSize(Utils.dp2px(14));
        paint.getFontMetrics(fontMetrics);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        canvas.drawBitmap(bitmap, getWidth() - IMAGE_WIDTH, IMAGE_OFFSET, paint);
        int length = text.length();
        float verticalOffset = - fontMetrics.top;
        for (int start = 0; start < length; ) {
            int maxWidth;
            float textTop = verticalOffset + fontMetrics.top;
            float textBottom = verticalOffset + fontMetrics.bottom;
            if (textTop > IMAGE_OFFSET && textTop < IMAGE_OFFSET + IMAGE_WIDTH
                    || textBottom > IMAGE_OFFSET && textBottom < IMAGE_OFFSET + IMAGE_WIDTH) {
                // 文字和圖片在同一行
                maxWidth = (int) (getWidth() - IMAGE_WIDTH);
            } else {
                // 文字和圖片不在同一行
                maxWidth = getWidth();
            }
            int count = paint.breakText(text, start, length, true, maxWidth, cutWidth);
            canvas.drawText(text, start, start + count, 0, verticalOffset, paint);
            start += count;
            verticalOffset += paint.getFontSpacing();
        }
    }

    Bitmap getAvatar(int width) {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(getResources(), R.drawable.jiqimao02, options);
        options.inJustDecodeBounds = false;
        options.inDensity = options.outWidth;
        options.inTargetDensity = width;
        return BitmapFactory.decodeResource(getResources(), R.drawable.jiqimao02, options);
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章