Android自定義View之定點寫文字

2021-09-11 13:01:46 字數 3920 閱讀 7980

前言:有經驗的android開發者,應該都會遇到在自定義view的時候,在view的某個地方寫文字,那麼當你在自定義的view中寫文字的時候,能夠做到定點寫文字嗎?能夠指哪寫哪嗎?寫出來的文字的位置和自己想要的位置一樣嗎?即使你最後寫的文字的位置和自己想象的位置是一樣的,那麼你知道其中的原理嗎?如果其中有乙個你不能回答出來,那就認真的閱讀本文吧!本文會給出你想要的答案...

看下下面的圖,假如下面的圖是我們要做出的效果

很簡單,有沒有?就是在乙個圓的中心寫文字。紅色的圓形很好畫出來,那麼我們怎麼將文字寫在圓的中心點上呢?第一時間想到的是拿到圓中心點的座標,然後直接呼叫drawtext()方法來寫文字。實現的**大致如下

@override

protected

void

ondraw

(canvas canvas)

複製**

現在,看下上面**實現的效果

上圖中的黃線是在圓的中心點畫的線,可以發現上面**實現的效果,明顯不是我們想要的效果,為什麼會這樣呢?下文會給出答案。

在android中自定義view的時候,怎麼讓系統知道應該在**畫出我們想要的圖形呢?比如畫上面的圓,這時我們就要告訴系統,我們要畫的圓形的圓心在什麼位置,告訴系統我們想要的圓的半徑是多少,然後系統就能在合適的位置畫出你想要的圓了。同樣,在畫文字的時候我們要指定文字在什麼位置,而指定的座標的位置就是文字的基線。

要理解drawtext()中的基線是什麼,需要先了解一下darwtext()方法,darwtext()方法有四個引數,如下

drawtext(@nonnull string text, float x, float y, @nonnull paint paint)

複製**

第乙個引數為你想要寫的內容,第二個引數為文字開始的x軸座標,第三個引數為文字開始的y軸座標,第四個引數為畫筆。以第二個第三個引數畫的一條水平線,就是drawtext()的基線。如上文中的第二張圖,黃色的線即為drawtext()基線,

注:第二和第三個引數不一定為文字開始的座標,也可能為文字中心的座標或則文字結尾的座標,具體是哪種座標與paint中的settextalign()方法有關。

可以得出結論,只要確定了基線的位置就確定了要畫的文字的位置了。那麼給定乙個座標,怎麼確定基線的位置呢?其實畫文字的時候,除了基線以外,還有其他幾條線,其他幾條線的位置如下圖

這幾條線的意義分別是:

這幾條線的位置可以通過fontmetrics物件獲得。

描述給定文字的各種度量值的類,它有五個成員變數,分別為topascentdescentbottomleading。這幾個成員變數的值都是相對基線位置的距離,如:

fontmetrics.top = top的y座標 - 基線

想要獲取fontmetrics,可以通過getfontmetrics()方法獲取,具體**如下

paint mpaint = new paint()

mpaint.settextsize(getresources().getdimensionpixelsize(r.dimen.sp18));

mpaint.setcolor(color.white);

mpaint.settextalign(paint.align.center);

mpaint.setstrokewidth(1);

paint.fontmetrics fontmetrics = mpaint.getfontmetrics();

複製**

使用fontmetrics獲取到的topascentdescentbottomleading成員變數的值,是相對於基線的距離,並不是座標,可以看下下圖,方便理解

可以發現topascent的值為負數,descentbottom的值為正數,為什麼會這樣呢?因為top線和ascent線在基線的上方,fontmetrics物件中的幾個成員變數的值都是表示相對基線的位置。

了解了fontmetrics再結合下圖

可以得到下面的公式:

根據得出的公式可以計算出基線的y座標

top的y座標 = 基線 + fontmetrics.top

基線 = top的y座標 - fontmetrics.top

實現的**如下

paint mpaint = new paint();

mpaint.settextsize(getresources().getdimensionpixelsize(r.dimen.sp18));

mpaint.setstrokewidth(1);

mpaint.setcolor(color.red);

paint.fontmetrics fontmetrics = mpaint.getfontmetrics();

float baseline = cy-fontmetrics.top;//cy指定點的y座標

canvas.drawtext("wizardev", 0, baseline, mpaint);

複製**

給定中間線寫文字,可以說是自定義view寫文字時用的最多的了,如,將文字寫在圓的正中間,如上圖,圓的中心線將文字平分,這種就是本文說的給定中間線寫文字。文章前面說了,只要確定了基線的位置,文字的位置也就確定了,那麼像這種,怎樣來確定基線的位置呢?這時我們可以借助其他的幾條線來計算出基線的位置。

如上圖,將topcenter之間的間距設為a,將centerbaseline之間的距離設為b,將centerbottom之間的距離設為c。這是就可以得出下面的公式

a = c = (bottom - top)/2

b = baseline - center

b = c - (bottom - baseline )

然後根據上文得到的公式:

bottom = fontmetrics.bottom + baseline

top = fontmetrics.top + baseline

可以將最上面的公式修改為:

baseline - center = (fontmetrics.bottom + baseline - fontmetrics.top - baseline) / 2 - (fontmetrics.bottom + baseline - baseline)

最後的到的公式為:

baseline = center - (fontmetrics.bottom - fontmetrics.top) / 2 + fontmetrics.bottom

上面的到的公式就是給出中心線的位置,最後計算出的基線所在位置的公式。

這種情況應該是最簡單的了,直接把給定點的y座標作為基線的y座標就行了。

Android自定義控制項之自定義View 二

效果如下圖 1 自定義ringview繼承view新增其構造方法並建立畫筆 public class ringview extends view protected boolean isrunning false public ringview context context public ring...

Android自定義View 自定義元件

自繪控制項也分兩種,自定義元件和自定義容器,自定義元件是繼承view類,自定義容器時繼承viewgrounp 今天主要分析下自定義元件 還是舉個例子來的實際些,假如我們要畫乙個最簡單的textview,首先想到的就是canvas.drawtext 方法,怎麼畫了?還是得一步一步來 1 寫乙個myte...

Android自定義View實現

android自定義view實現很簡單 繼承view或者其子類,重寫建構函式 ondraw,onmeasure 等函式,根據繼承的類的不同可能有所不同。如果自定義的view需要有自定義的屬性,需要在values下建立attrs.xml。在其中定義你的屬性。在使用到自定義view的xml布局檔案中需要...