Canvas中的書法家講解與實戰——Android高級UI

目錄java

1、前言git

2、Canvas中的書法家APIgithub

3、實戰canvas

4、寫在最後微信

1、前言

canvas 的 API 方法至關之多,小盆友本篇文章以前已經分享了 「Canvas中的裁剪師」「Canvas中的繪圖師」,今天分享的是文字方面的API。ide

在分享前,小盆友囉嗦兩句,有些童鞋說 canvas 的這幾篇文章是初級文章和 「Android高級UI」 這幾個字顯得有些格格不入。小盆友藉此解釋下,canvas 的這幾篇文章是做爲 高級UI 文章的補充,是這系列文章中的 墊腳石,並不是想作 「標題黨」 來吸引流量(貌似一直也沒什麼流量😂)。函數

囉嗦了這麼多,來看看今天的實戰效果圖post

抖動的字符 動畫

2、Canvas中的書法家API

一、drawText(四個重載方法)

(1)第一個 drawText 函數編碼

public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) 複製代碼

描述: 在座標爲 (x,y) 處繪製 text 字符串。

舉個例子:

private static final String CONTENT = "zinc 猛猛的小盆友";

canvas.drawText(CONTENT, -300, -500, mPaint);
複製代碼

效果圖

(2)第二個 drawText 函數

public void drawText(@NonNull String text, int start, int end, float x, float y, @NonNull Paint paint) 複製代碼

描述: 在座標爲 (x,y) 處繪製字符串text,從下標爲start的字符開始,到下標爲 (end-1) 的字符終止。

舉個例子:

private static final String CONTENT = "zinc 猛猛的小盆友";

// 繪製內容爲從CONTENT的第四個字符開始,到CONTENT最後一個字符
canvas.drawText(CONTENT, 3, CONTENT.length(), -300, -400, mPaint);
複製代碼

效果圖

(3)第三個 drawText 函數

public void drawText(@NonNull char[] text, int index, int count, float x, float y, @NonNull Paint paint) 複製代碼

描述: 在座標爲 (x,y) 處繪製 text,從下標爲start開始,繪製count個字符。

舉個例子

private static final char[] C = "https://github.com/zincPower/UI2018".toCharArray();

canvas.drawText(C, 0, C.length, -300, -100, mPaint);
canvas.drawText(C, 5, 10, -300, 0, mPaint);
複製代碼

效果圖

(4)第四個 drawText 函數

public void drawText(@NonNull CharSequence text, int start, int end, float x, float y, @NonNull Paint paint) 複製代碼

描述: 在座標爲 (x,y) 處繪製 text,從下標爲start的字符開始,到下標爲 (end-1) 的字符終止。

舉個例子

private static final CharSequence SEQ = "https://blog.csdn.net/weixin_37625173";

canvas.drawText(SEQ, 0, SEQ.length(), -300, 300, mPaint);
canvas.drawText(SEQ, 6, 20, -300, 400, mPaint);
複製代碼

效果圖

二、drawTextOnPath (兩個重載方法)

(1)第一個 drawTextOnPath 函數

public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset, float vOffset, @NonNull Paint paint) 複製代碼

描述:路徑path 上繪製 text。

特殊參數說明: 1)hOffset:水平偏移量 2)vOffset:垂直偏移量

舉個例子

private static final String CONTENT = "zinc 猛猛的小盆友";

// mPath 是一個貝塞爾曲線繪製的路徑
canvas.drawTextOnPath(CONTENT, mPath, 0, 0, mPaint);
複製代碼

效果圖

(2)第二個 drawTextOnPath 函數

public void drawTextOnPath(@NonNull char[] text, int index, int count, @NonNull Path path, float hOffset, float vOffset, @NonNull Paint paint) 複製代碼

描述:路徑path 上繪製 text。

特殊參數說明: 1)index:從下標爲index的字符開始繪製 2)count:繪製字符的個數 3)hOffset:水平偏移量 4)vOffset:垂直偏移量

例子

private static final char[] C = "https://blog.csdn.net/weixin_37625173".toCharArray();

// 從下標爲2的字符(即第三個字符)開始,繪製20個字符
canvas.drawTextOnPath(C, 2, 20, mPath, 0, 0, mPaint);
複製代碼

效果圖

三、drawTextRun

這個方法不作過多的解釋,由於在實際開發中使用能夠說較少。簡單歸納這個方法的做用,他是爲了處理一些語言文字(例如:阿拉伯語),當一個字在一個詞語中,會受左右的字影響而進行變形的狀況。

這方面的語言小盆友不懂,因此無法舉出嚴謹的例子,請有須要的童鞋移步Demo中自行體會。

public void drawTextRun(@NonNull char[] text, int index, int count, int contextIndex, int contextCount, float x, float y, boolean isRtl, @NonNull Paint paint) public void drawTextRun(@NonNull CharSequence text, int start, int end, int contextStart, int contextEnd, float x, float y, boolean isRtl, @NonNull Paint paint) 複製代碼

四、drawPosText(兩個重載方法)

(1)第一個 drawPosText 函數

public void drawPosText(@NonNull String text, @NonNull @Size(multiple = 2) float[] pos, @NonNull Paint paint) 複製代碼

描述: 在pos對應的座標上繪製text。

舉個例子

private static final String CONTENT = "猛猛的小盆友";
private static final float[] pos1 = new float[]{
        -300, -600,
        -250, -500,
        -200, -400,
        -150, -300,
        -100, -200,
        -50, -100,
};

// 每一個字符 和 pos的座標要一一對應的上,不然crash
canvas.drawPosText(CONTENT, pos1, mPaint);
複製代碼

效果圖

(2)第二個 drawPosText 函數

public void drawPosText(@NonNull char[] text, int index, int count, @NonNull @Size(multiple = 2) float[] pos, @NonNull Paint paint) 複製代碼

描述: 在pos對應的座標上繪製text,從下標爲index的字符開始,繪製count個。

舉個例子

private static final String CONTENT = "猛猛的小盆友";
private static final float[] pos2 = new float[]{
        -300, 100,
        -250, 200,
        -200, 300,
        -150, 400,
        -100, 500,
};

canvas.drawPosText(CONTENT.toCharArray(), 1, 4, pos2, mPaint);
複製代碼

效果圖

3、實戰

抖動的字符

Github入口:傳送門

編碼思路 在這一實戰中,其實 drawTextOnPath 反倒不是主角,他只是負責在咱們的 path 上將文字繪出便可,因此童鞋們知道了最主要的是 path 的肯定。

獲取 path 上的點,是經過以下的函數獲取

private float calculateY(float x) {
    double a = Math.pow(4 / (4 + Math.pow(4 * x / mLength, 4)), 2.5f) * mA;
    return (float) (a * Math.sin(Math.PI * x / 200 - m));
}
複製代碼

具體的函數圖形以下

公式的最初原型來源於此博客,在此謝謝博主。

看完這函數,可能有些童鞋比較懵逼,小盆友稍微給一些簡單解釋(畢竟難的我也說不清😂),咱們將此公式抽象一下,即是以下形狀:

A*sin(w*x+m)+k
複製代碼

這就是咱們在初中學的三角函數:正弦函數sin。咱們羅列下幾個參數的做用:

  • A:管理 正弦函數 的振幅,即上下襬動的幅度;
  • w:管理 正弦函數 的水平收縮幅度
  • m:管理 正弦函數 的水平偏移量
  • k:管理 正弦函數 的垂直偏移量

在咱們這裏的場景中,主要控制兩個參數:

  1. A 的振幅變更,上面函數圖中在靠近 x=0 的地方函數的震動幅度變大,因此咱們將 x的值 考慮進 A的計算中,而且以分母的形式(分母越大,數值越小;分母越小,數值越大)
  2. m 的水平偏移,正弦的一個週期是 2π,因此咱們這裏的曲直只須要從 [0-2π] 的一個範圍便可。

讓字符串搖擺起來 通過上面的簡單分析,咱們須要的各類零件也都準備好了,最後加入咱們再熟悉不過的 屬性動畫,就可讓這條 路徑path 動起來。路徑path 動起來,會致使繪製在上面文字也動起來。

mAnimator = ValueAnimator.ofFloat(0, (float) (2 * Math.PI));
mAnimator.setInterpolator(new LinearInterpolator());
mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float progress = (float) animation.getAnimatedValue();
        m = progress;
        mA = (float) (1 - progress / (2 * Math.PI)) * A;
        invalidate();
    }
});
mAnimator.setDuration(1000);
複製代碼

4、寫在最後

此次的文章較爲簡單和基礎,只是小盆友有點強迫症,必需要把 canvas 的每一個API都過一遍和記錄一下。

若是以爲文章對你有所啓發,請給我個贊吧,若是發現有那些欠妥的地方,請留言區與我討論,咱們共同進步。

高級UI系列的Github地址:請進入傳送門,若是喜歡的話給我一個star吧😄

歡迎加我微信,咱們能夠進行更多更有趣的交流

相關文章
相關標籤/搜索