編輯:關於Android編程
本來這篇文章是要寫寫我在設計高級跑馬燈程序的心得的,但是編寫過程中花了近一天多的時間搞明白canvas.drawText中的第三個參數[float y]代表的真實含義。學習本文應該能幫助大家掌握FontMetrics類和Rect類成員變量值具體含義。
先來看看api中是如何定義drawText的參數。
/**
* Draw the text, with origin at (x,y), using the specified paint. The
* origin is interpreted based on the Align setting in the paint.
*
* @param text The text to be drawn
* @param x The x-coordinate of the origin of the text being drawn
* @param y The y-coordinate of the baseline of the text being drawn
* @param paint The paint used for the text (e.g. color, size, style)
*/
public void drawText(@NonNull String text, float x, float y, @NonNull Paint paint) {
native_drawText(mNativeCanvasWrapper, text, 0, text.length(), x, y, paint.mBidiFlags,
paint.getNativeInstance(), paint.mNativeTypeface);
}
簡單解釋下各參數:
@param text:要顯示的文本內容,這個不難理解。
@param x:文本相對屏幕原點x方向距離,沒有更深的含義,也比較好理解
@param y:文本的baseline相對屏幕原點y方向距離。好,問題來了,baseline是個什麼鬼東東
@param paint:畫筆
先看看baseline在文字區域的位置。通過一個實例來分析,這裡只貼主要的code。
@Override
protected void onDraw(Canvas canvas) {
//super.onDraw(canvas);
mRect = new Rect();
mPaint = new Paint();
mPaint.setTextSize(64);
mPaint.setColor(Color.RED);
Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt();
mPaint.getTextBounds(textStr, 0, textStr.length(), mRect);
int w = mRect.width();
int h = mRect.height();
mRect = new Rect(mRectLeft, mRectTop, mRectLeft+w, mRectTop+(-fontMetrics.top)+fontMetrics.bottom);
canvas.drawRect(mRect, mPaint);
mBaseLine = (mRect.bottom+mRect.top)/2
- (fontMetrics.bottom+fontMetrics.top)/2;
mBaseLine = -fontMetrics.top;
/*其中y == mBaseLine的值*/
mPaint.setColor(Color.WHITE);
canvas.drawText(textStr, mRectLeft, mBaseLine, mPaint);
mPaint.setColor(Color.BLUE);
mPaint.setStrokeWidth(3);
/*將mBaseLine所在的位置畫出來*/
canvas.drawLine(mRectLeft, mBaseLine, mRectLeft+w, mBaseLine, mPaint);
}
效果圖:
從上圖可以看出來,baseline並不是文字區域的底部,但是這根線的位置相信大家都熟悉,除非你沒有學過英語。
FontMetrics是Paint靜態內部類,主要定義了Paint繪制文本時的關鍵坐標。API中這麼描述:
Class that describes the various metrics for a font at a given text size. Remember, Y values increase going down, so those values will be positive, and values that measure distances going up will be negative. This class is returned by getFontMetrics().
主要意思:根據設定的fontsize來獲得字體的各種變量值。通過getFontMetrics()方法來獲取。
FontMetrics類含有5個成員變量:
public static class FontMetrics {
/**
* The maximum distance above the baseline for the tallest glyph in
* the font at a given text size.
*/
public float top;
/**
* The recommended distance above the baseline for singled spaced text.
*/
public float ascent;
/**
* The recommended distance below the baseline for singled spaced text.
*/
public float descent;
/**
* The maximum distance below the baseline for the lowest glyph in
* the font at a given text size.
*/
public float bottom;
/**
* The recommended additional space to add between lines of text.
*/
public float leading;
}
很明顯所有的值都是基於baseline來算的。這裡我主要關注top這個值的定義。
top:api的注釋翻譯過來意思是字體可繪制區域最高位置與baseline的距離。但是它是個負數,所以-top就是我們的baseline坐標值。
ascent:字體下單個字符最高位置與baseline的距離
descent:字體下單個字符最低位置與baseline的距離,與ascent鏡像對應
bottom:字體可繪制區域最低位置與baseline的距離。
leading:字面翻譯是文本線額外的空間。一般都為0,不知道有何用處。
Rect類表示的一塊矩形區域。Paint類中getTextBounds()方法可以獲取對應font size下文本所占用矩形區域。記住這個矩形區域的坐標值也是相對baseline來計算的。
Rect類成員變量有4個,分別是left、top、right、bottom。由於文本的rect區域是相對baseline來計算的,因此真實的top跟bottom都要加上baseline的值。
主要源碼:
@Override
protected void onDraw(Canvas canvas) {
//super.onDraw(canvas);
mRect = new Rect();
mPaint = new Paint();
mPaint.getTextBounds(textStr, 0, 1, mRect);
mPaint.setTextSize(textSize);
mPaint.setColor(0xffF4A460);
Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt();
mPaint.getTextBounds(textStr, 0, textStr.length(), mRect);
int w = mRect.width();
int h = mRect.height();
/*給fontMetrics區域填充0xffF4A460色*/
mRect = new Rect(mRectLeft, mRectTop, mRectLeft+w, mRectTop+(-fontMetrics.top)+fontMetrics.bottom);
canvas.drawRect(mRect, mPaint);
/*計算baseline,其中mRectTop是控件頂部到父view的距離*/
mBaseLine = -fontMetrics.top + mRectTop;
/*其中y == mBaseLine的值*/
mPaint.setColor(Color.WHITE);
canvas.drawText(textStr, mRectLeft, mBaseLine, mPaint);
mPaint.setColor(Color.BLUE);
mPaint.setStrokeWidth(4);
/*藍色線:將mBaseLine所在的位置畫出來*/
canvas.drawLine(mRectLeft, mBaseLine, mRectLeft+w, mBaseLine, mPaint);
mPaint.setColor(Color.GREEN);
/*綠色線:將文字區域的bottom所在的位置畫出來*/
canvas.drawLine(mRectLeft, mBaseLine+fontMetrics.bottom, mRectLeft+2*w
, mBaseLine+fontMetrics.bottom, mPaint);
mPaint.setColor(Color.RED);
/*紅色線:將文字區域的top所在的位置畫出來*/
canvas.drawLine(mRectLeft, mBaseLine+fontMetrics.top, mRectLeft+2*w
, mBaseLine+fontMetrics.top, mPaint);
mPaint.setColor(Color.GRAY);
/*灰色線:將文字區域的ascent所在的位置畫出來*/
canvas.drawLine(mRectLeft, mBaseLine+fontMetrics.ascent, mRectLeft+w+50
, mBaseLine+fontMetrics.ascent, mPaint);
mPaint.setColor(Color.WHITE);
/*白色線:將文字區域的descent所在的位置畫出來*/
canvas.drawLine(mRectLeft, mBaseLine+fontMetrics.descent, mRectLeft+w+50
, mBaseLine+fontMetrics.descent, mPaint);
mPaint.setColor(Color.YELLOW);
/*黃色線:將文字區域的leading所在的位置畫出來*/
canvas.drawLine(mRectLeft, mBaseLine+fontMetrics.leading, mRectLeft+w/2
, mBaseLine+fontMetrics.leading, mPaint);
/*將“測”字的rect用矩形繪出來*/
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.getTextBounds(textStr, 0, 1, mRect);
mRect.top+=mBaseLine;
mRect.bottom+=mBaseLine;
canvas.drawRect(mRect, mPaint);
/*將“測試:12hg”字的rect用矩形繪出來*/
mPaint.setColor(Color.BLACK);
mPaint.setStyle(Paint.Style.STROKE);
mPaint.getTextBounds(textStr, 0, 7, mRect);
mRect.top+=mBaseLine;
mRect.bottom+=mBaseLine;
canvas.drawRect(mRect, mPaint);
}
效果圖:
FontMetrics:
1. 淺黃色區域就是文字的FontMetrics區域,可以看出來文字實在此區域垂直居中繪制
2. 紅色線:為FontMetrics的top
3. 灰色線:為FontMetrics的ascent
4. 黃色線:為FontMetrics的leading
5. 藍色線:為baseline線
6. 白色線:為FontMetrics的descent
7. 綠色線:為FontMetrics的bottom
Rect:
1. 第一個小黑矩形為“測”字的rect區域
2. 第二個長黑矩形為“測試:12hg”字的rect區域
只要徹底弄明白baseline才能輕松掌握drawText接口,才不至於開發的時候總是搞不明白繪制的文字要麼偏上要麼偏下。
前言之前的一篇文章:基於RxJava實現酷炫啟動頁 中,我們嘗試了用RxJava實現酷炫的啟動頁,今天我們在此基礎上加入首次使用APP時的引導頁功能。效果如下圖:思路:思
1、本地html與本地html裡的js交互2、本地html與本地js交互3、網絡html與網絡js交互4、網絡html與本地js交互5、各個情況動態添加js以上5點都可以
一,介紹android四大組件之一:BroadcastReceiver 翻譯成中文:廣播接收者。在Android中,Broadcast是一種廣泛運用在應用程序之間傳輸信息
monkeyrunner腳本錄制1.在窗口輸入 monkeyrunner monkey_recorder.py 調用錄制腳本工具2.在窗口輸入 monkeyr