1. 程式人生 > >android自定義View學習3--文字繪製

android自定義View學習3--文字繪製

介紹一大堆繪製文字相關的函式…

主要分canvas繪製文字、Paint輔助繪製文字、Paint測量文字相關值。

1. canvas繪製文字

1) drawText(String text, float x, float y, Paint paint)

canvas.drawText(text, 200, 100, paint);

text 是文字內容,x 和 y 是文字的座標。
注意:這個座標並不是文字的左上角,而是一個與左下角比較接近的位置。

2) drawTextRun(CharSequence text, int start, int end, int contextStart, int contextEnd, float x, float y, boolean isRtl, Paint paint)

用來繪製某些特殊外國文字,如阿拉伯文字等。
text:要繪製的文字
start:從那個字開始繪製
end:繪製到哪個字結束
contextStart:上下文的起始位置。contextStart 需要小於等於 start
contextEnd:上下文的結束位置。contextEnd 需要大於等於 end
x:文字左邊的座標
y:文字的基線座標
isRtl:是否是 RTL(Right-To-Left,從右向左)

3) drawTextOnPath(String text, Path path, float hOffset, float vOffset, Paint paint)

canvas.drawTextOnPath("Hello HeCoder", path, 0, 0, paint); 

hOffset :文字相對於 Path 的水平偏移量
vOffset :文字相對於 Path 的豎直偏移量,
例如:設定 hOffset 為 5, vOffset 為 10,文字就會右移 5 畫素和下移 10 畫素。

4) StaticLayout(CharSequence source, TextPaint paint, int width, Layout.Alignment align, float spacingmult, float spacingadd, boolean includepad)

StaticLayout 用來繪製換行文字
它並不是一個 View 或者 ViewGroup ,而是 android.text.Layout 的子類,它是純粹用來繪製文字的。 StaticLayout 支援換行,它既可以為文字設定寬度上限來讓文字自動換行,也會在 \n 處主動換行。

String text1 = "Lorem Ipsum is simply dummy text of the printing and typesetting industry.";  
StaticLayout staticLayout1 = new StaticLayout(text1, paint, 600,  
        Layout.Alignment.ALIGN_NORMAL, 1, 0, true);
String text2 = "a\nbc\ndefghi\njklm\nnopqrst\nuvwx\nyz";  
StaticLayout staticLayout2 = new StaticLayout(text2, paint, 600,  
        Layout.Alignment.ALIGN_NORMAL, 1, 0, true);

...

canvas.save();  
canvas.translate(50, 100);  
staticLayout1.draw(canvas);  
canvas.translate(0, 200);  
staticLayout2.draw(canvas);  
canvas.restore();  

width 是文字區域的寬度,文字到達這個寬度後就會自動換行;
align 是文字的對齊方向;
spacingmult 是行間距的倍數,通常情況下填 1 就好;
spacingadd 是行間距的額外增加值,通常情況下填 0 就好;
includeadd 是指是否在文字上下新增額外的空間,來避免某些過高的字元的繪製出現越界。

2. 使用Paint輔助繪製文字

1) setTextSize(float textSize)

設定文字大小。

paint.setTextSize(18);  
canvas.drawText(text, 100, 25, paint); 

2) setTypeface(Typeface typeface)

設定字型。

paint.setTypeface(Typeface.DEFAULT); //預設字型
canvas.drawText(text, 100, 150, paint);  
paint.setTypeface(Typeface.SERIF);//宋體
canvas.drawText(text, 100, 300, paint);  
paint.setTypeface(Typeface.createFromAsset(getContext().getAssets(), "Satisfy-Regular.ttf"));//使用自定義字型
canvas.drawText(text, 100, 450, paint); 

3) setFakeBoldText(boolean fakeBoldText)

設定文字是否加粗(偽粗體,因為實質上只是多繪製了幾遍,而不是使用粗體)。

paint.setFakeBoldText(false);  
canvas.drawText(text, 100, 150, paint);  
paint.setFakeBoldText(true);  
canvas.drawText(text, 100, 230, paint); 

4) setStrikeThruText(boolean strikeThruText)

設定文字是否加刪除線。(就是文字中間畫一橫)

paint.setStrikeThruText(true);  
canvas.drawText(text, 100, 150, paint); 

5) setUnderlineText(boolean underlineText)

設定文字是否加下劃線。

paint.setUnderlineText(true);  
canvas.drawText(text, 100, 150, paint);  

6) setTextSkewX(float skewX)

設定文字橫向錯切角度。(其實就是文字傾斜度)
當skewX為負時,向右傾斜;為正是向左傾斜。

paint.setTextSkewX(-0.5f);  
canvas.drawText(text, 100, 150, paint);

7) setTextScaleX(float scaleX)

設定文字橫向放縮。(也就是文字變寬變窄)
scaleX為1,文字不變;
scaleX小於1,文字變窄;
scaleX大於1,文字變寬;

paint.setTextScaleX(1);  
canvas.drawText(text, 100, 150, paint);  
paint.setTextScaleX(0.8f);  
canvas.drawText(text, 100, 230, paint);  
paint.setTextScaleX(1.2f);  
canvas.drawText(text, 100, 310, paint);

8) setLetterSpacing(float letterSpacing)

設定字元間距。預設值是 0(這時還是有預設的間隙的)。
letterSpacing大於0時,間隙擴大。

paint.setLetterSpacing(0.2f);  
canvas.drawText(text, 100, 150, paint); 

9) setFontFeatureSettings(String settings)

用 CSS 的 font-feature-settings 的方式來設定文字。

paint.setFontFeatureSettings("smcp"); // 設定 "small caps"  
canvas.drawText("Hello HenCoder", 100, 150, paint);  

10) setTextAlign(Paint.Align align)

設定文字的對齊方式。一共有三個值:LEFT CETNER 和 RIGHT。預設值為 LEFT。
注意:文字的對齊是以座標為基準的。即:

  • 左對齊就是文字串的左邊在設定的座標上;
  • 右對齊就是文字串的右邊在設定的座標上;
  • 居中對齊就是文字串的中間在設定的座標上;

不要認為左對齊,文字就靠在最左邊,相反,文字的最左邊在設定的座標位置時,文字本身是在座標右邊的。

paint.setTextAlign(Paint.Align.LEFT);  
canvas.drawText(text, 500, 150, paint);  
paint.setTextAlign(Paint.Align.CENTER);  
canvas.drawText(text, 500, 150 + textHeight, paint);  
paint.setTextAlign(Paint.Align.RIGHT);  
canvas.drawText(text, 500, 150 + textHeight * 2, paint); 

11) setTextLocale(Locale locale) / setTextLocales(LocaleList locales)

設定繪製所使用的 Locale。就是手機系統裡的語言區域啦。

paint.setTextLocale(Locale.CHINA); // 簡體中文  
canvas.drawText(text, 150, 150, paint);  
paint.setTextLocale(Locale.TAIWAN); // 繁體中文  
canvas.drawText(text, 150, 150 + textHeight, paint);  
paint.setTextLocale(Locale.JAPAN); // 日語  
canvas.drawText(text, 150, 150 + textHeight * 2, paint);  

12) setHinting(int mode)

設定是否啟用字型的 hinting (字型微調)。
如今手機螢幕的畫素密度已經非常高,不需要修正了,此方法可忽略。

13) setElegantTextHeight(boolean elegant)

此方法只是對某些特殊國家文字(如泰文)有用,作用是是否還原顯示其原有高度(因為有些文字太高,繪製時預設壓縮了)。

paint.setFontFeatureSettings("smcp"); // 設定 "small caps"  
canvas.drawText("Hello HenCoder", 100, 150, paint);  

14) setFontFeatureSettings(String settings)

用 CSS 的 font-feature-settings 的方式來設定文字。

paint.setElegantTextHeight(true); 

15) setSubpixelText(boolean subpixelText)

是否開啟次畫素級的抗鋸齒( sub-pixel anti-aliasing )。
應該就是很厲害的抗鋸齒吧~~~~

3. Paint測量文字尺寸

1) float getFontSpacing()

獲取推薦的行距。
即推薦的兩行文字的 baseline(就是文字最下面的靠近文字的線) 的距離。這個值是系統根據文字的字型和字號自動計算的。

canvas.drawText(texts[0], 100, 150, paint);  
canvas.drawText(texts[1], 100, 150 + paint.getFontSpacing, paint);  
canvas.drawText(texts[2], 100, 150 + paint.getFontSpacing * 2, paint);  

2) FontMetircs getFontMetrics()

獲取 Paint 的 FontMetrics。
FontMetrics 是個相對專業的工具類,它提供了幾個文字排印方面的數值:ascent, descent, top, bottom, leading。

  • ascent : 字元的上界
  • descent : 字元的下界
  • top : 字形的上界
  • bottom : 字形的下界
  • leading : 上行的 bottom 線和下行的 top 線的距離

可以通過
FontMetrics.ascent:float 型別。
FontMetrics.descent:float 型別。
FontMetrics.top:float 型別。
FontMetrics.bottom:float 型別。
FontMetrics.leading:float 型別。
來獲得它們的值。
也可以通過Paint.ascent() 和 Paint.descent() 來快捷獲取。

3) getTextBounds(String text, int start, int end, Rect bounds)

獲取文字的顯示範圍。
text 是要測量的文字,start 和 end 分別是文字的起始和結束位置,bounds 是儲存文字顯示範圍的物件,方法在測算完成之後會把結果寫進 bounds。

paint.setStyle(Paint.Style.FILL);  
canvas.drawText(text, offsetX, offsetY, paint);

paint.getTextBounds(text, 0, text.length(), bounds);  
bounds.left += offsetX;  
bounds.top += offsetY;  
bounds.right += offsetX;  
bounds.bottom += offsetY;  
paint.setStyle(Paint.Style.STROKE);  
canvas.drawRect(bounds, paint);  

4) float measureText(String text)

測量文字繪製時所佔用的寬度並返回。

canvas.drawText(text, offsetX, offsetY, paint);  
float textWidth = paint.measureText(text);  
canvas.drawLine(offsetX, offsetY, offsetX + textWidth, offsetY, paint); 

5) getTextWidths(String text, float[] widths)

獲取字串中每個字元的寬度,並把結果填入引數 widths

6) int breakText(String text, boolean measureForwards, float maxWidth, float[] measuredWidth)

這個方法也是用來測量文字寬度的。但和 measureText() 的區別是, breakText() 是在給出寬度上限的前提下測量文字的寬度。如果文字的寬度超出了上限,那麼在臨近超限的位置截斷文字。

breakText() 的返回值是擷取的文字個數(如果寬度沒有超限,則是文字的總個數)。引數中, text 是要測量的文字;measureForwards 表示文字的測量方向,true 表示由左往右測量;maxWidth 是給出的寬度上限;measuredWidth 是用於接受資料,而不是用於提供資料的:方法測量完成後會把擷取的文字寬度(如果寬度沒有超限,則為文字總寬度)賦值給 measuredWidth[0]。

int measuredCount;  
float[] measuredWidth = {0};

// 寬度上限 300 (不夠用,截斷)
measuredCount = paint.breakText(text, 0, text.length(), true, 300, measuredWidth);  
canvas.drawText(text, 0, measuredCount, 150, 150, paint);

// 寬度上限 400 (不夠用,截斷)
measuredCount = paint.breakText(text, 0, text.length(), true, 400, measuredWidth);  
canvas.drawText(text, 0, measuredCount, 150, 150 + fontSpacing, paint);

// 寬度上限 500 (夠用)
measuredCount = paint.breakText(text, 0, text.length(), true, 500, measuredWidth);  
canvas.drawText(text, 0, measuredCount, 150, 150 + fontSpacing * 2, paint);

// 寬度上限 600 (夠用)
measuredCount = paint.breakText(text, 0, text.length(), true, 600, measuredWidth);  
canvas.drawText(text, 0, measuredCount, 150, 150 + fontSpacing * 3, paint);  

7) getRunAdvance(CharSequence text, int start, int end, int contextStart, int contextEnd, boolean isRtl, int offset)

對於一段文字,計算出某個字元處游標的 x 座標

start、end 是文字的起始和結束座標;
contextStart contextEnd :上下文的起始和結束座標;
isRtl :文字的方向;
offset :字數的偏移,即計算第幾個字元處的游標。

int length = text.length();  
float advance = paint.getRunAdvance(text, 0, length, 0, length, false, length);  
canvas.drawText(text, offsetX, offsetY, paint);  
canvas.drawLine(offsetX + advance, offsetY - 50, offsetX + advance, offsetY + 10, paint);  

8) getOffsetForAdvance(CharSequence text, int start, int end, int contextStart, int contextEnd, boolean isRtl, float advance)

給出一個位置的畫素值,計算出文字中最接近這個位置的字元偏移量(即第幾個字元最接近這個座標)

text : 要測量的文字;
contextStart contextEnd : 上下文的起始和結束座標;
isRtl : 文字方向(從右向左);
advance : 給出的位置的畫素值。

填入引數,對應的字元偏移量將作為返回值返回。

9) hasGlyph(String string)

檢查指定的字串中是否是一個單獨的字形 (glyph)。最簡單的情況是,string 只有一個字母(比如 a)。
字串:a,hasGlyph(“a”)為true
字串:ab,hasGlyph(“ab”)為false

啊。。。太多了。這些記不住的,能知道,有個印象就像,回頭再來查吧~~~~