感謝您的點贊和關注!

『前提』

更新日誌:

2021-11-13==V.1.1

2019-1-13==V.1

即將學會

利用TextView的onTextChanged方法來實現寬度高度自適應的控制元件,目前只適用於單行。

背景

小空:出現的原因是專案需要的裝置廣(涉及到手機/平板/大電視/無數的定製裝置)。如果是知名的品牌還好,關鍵客戶還是一些亂七八糟的品牌,無數尺寸造成的螢幕密度。

小芝:你說氣人不氣人。我都炸了。

小空(嘆氣):關鍵又沒給更多的適配開始時間。這就很傷人了,如果使用資原始檔values適配的話,那燒香都怕香不夠,甚至引發一連串的事故。

小芝(疑問):所以呢?有解決辦法嗎!

小空:那當然,雖然是取巧的形式,但好歹解決了問題。最開始的時候也是沒有思路,在GitHub上搜索了半天,終於找到了類似的開源:AutoFitTextView,截止2021-8-2擁有800多Star。其他也搜尋到了不少,但是並不滿足解決需求。

小芝(很開心):哇,感謝開源。

實踐過程

目前適應的範圍:TextView無寬高限制;無其他限制; 不過專案中使用的權重佈局,可根據情況調整!實現的結果:在下方圖的控制元件上回自動填充滿,控制元件大,字型大,控制元件小,字型小!

Android自定義TextView實現高度和寬度,解決字型適配問題

程式:註釋解釋很全

import

android。content。Context

import

android。graphics。Paint

import

android。support。annotation。Nullable

import

android。text。TextPaint

import

android。util。AttributeSet

import

android。view。Gravity

import

android。widget。TextView

/**

* Created by akitaka on 2018-07-05。

* https://zhima。blog。csdn。net/

* https://juejin。cn/user/4265760844943479/columns

* https://www。zhihu。com/people/zhimalier

* @filename FitHeightTextView

* @describe 根據高度自適應字型文字大小

* @email 960576866@qq。com */

public

class

FitHeightTextView

extends

TextView

{

private

Paint

mTextPaint

private

float

mMaxTextSize

// 獲取當前所設定文字大小作為最大文字大小

private

float

mMinTextSize

=

8

//最小的字型大小

public

FitHeightTextView

Context

context

{

super

context

);

}

public

FitHeightTextView

Context

context

@Nullable

AttributeSet

attrs

{

super

context

attrs

);

setGravity

getGravity

()

|

Gravity

CENTER_VERTICAL

);

// 預設水平居中

setLines

1

);

initialise

();

}

private

void

initialise

()

{

mTextPaint

=

new

TextPaint

();

mTextPaint

set

this

getPaint

());

//預設的大小是設定的大小,如果撐不下了 就改變

mMaxTextSize

=

this

getTextSize

();

}

//文字改變的時候

@Override

protected

void

onTextChanged

CharSequence

text

int

start

int

lengthBefore

int

lengthAfter

{

refitText

text

toString

(),

this

getHeight

());

//textview檢視的高度

super

onTextChanged

text

start

lengthBefore

lengthAfter

);

}

private

void

refitText

String

textString

int

height

{

if

height

>

0

{

//減去邊距為字型的實際高度

int

availableHeight

=

height

-

this

getPaddingTop

()

-

this

getPaddingBottom

();

float

trySize

=

mMaxTextSize

mTextPaint

setTextSize

trySize

);

while

mTextPaint

descent

()-

mTextPaint

ascent

()

>

availableHeight

{

//測量的字型高度過大,不斷地縮放

trySize

-=

1

//字型不斷地減小來適應

if

trySize

<=

mMinTextSize

{

trySize

=

mMinTextSize

//最小為這個

break

}

mTextPaint

setTextSize

trySize

);

}

setTextSize

px2sp

getContext

(),

trySize

));

}

}

//大小改變的時候

@Override

protected

void

onSizeChanged

int

w

int

h

int

oldw

int

oldh

{

if

h

!=

oldh

{

refitText

this

getText

()。

toString

(),

h

);

}

}

/**

* 將px值轉換為sp值,保證文字大小不變

*/

public

static

float

px2sp

Context

context

float

pxValue

{

float

fontScale

=

context

getResources

()。

getDisplayMetrics

()。

scaledDensity

return

pxValue

/

fontScale

);

}

}

在佈局中使用的話,注意按照你最大的裝置來設定字型大小,這樣在小裝置上回自動縮放

android:textSize 保持為支援最大裝置的字型大小

android:layout_width=“wrap_content”

android:layout_height=“wrap_content”

android:gravity=“center_vertical”

android:text=“設定”

android:textSize=“28sp”

android:textColor=“#56BBe0” />

試驗後就會發現,真的很神奇;

有根據高度,就有根據寬度的自動適配,這個是網上的,同時github上也大多是這種效果;上個簡單的程式碼

/**

* Created by akitaka on 2018-07-05。

* https://zhima。blog。csdn。net/

* https://juejin。cn/user/4265760844943479/columns

* https://www。zhihu。com/people/zhimalier

* @filename FitHeightTextView

* @describe 根據高度自適應字型文字大小

* @email 960576866@qq。com */public class FitTextView extends TextView{

private Paint mTextPaint;

private float mMaxTextSize; // 獲取當前所設定文字大小作為最大文字大小

private float mMinTextSize = 3;

public FitTextView(Context context) {

this(context, null);

}

public FitTextView(Context context, AttributeSet attrs) {

super(context, attrs);

setGravity(getGravity() | Gravity。CENTER_VERTICAL); // 預設水平居中

setLines(1);

initialise();

}

@Override

protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {

refitText(text。toString(), this。getWidth());

super。onTextChanged(text, start, lengthBefore, lengthAfter);

}

private void initialise() {

mTextPaint = new TextPaint();

mTextPaint。set(this。getPaint());

// 最大的大小預設為特定的文字大小,除非它太小了

mMaxTextSize = this。getTextSize();

// mMinTextSize = 8;

}

@Override

protected void onSizeChanged(int w, int h, int oldw, int oldh) {

if (w != oldw) {

refitText(this。getText()。toString(), w);

}

}

/**

* Resize the font so the specified text fits in the text box

* assuming the text box is the specified width。

*

*/

private void refitText(String text, int textWidth) {

if (textWidth > 0) {

int availableWidth = textWidth - this。getPaddingLeft() - this。getPaddingRight();

float trySize = mMaxTextSize;

mTextPaint。setTextSize(trySize);

while (mTextPaint。measureText(text) > availableWidth) {

trySize -= 1;

if (trySize <= mMinTextSize) {

trySize = mMinTextSize;

break;

}

mTextPaint。setTextSize(trySize);

}

// setTextSize引數值為sp值

setTextSize(px2sp(getContext(), trySize));

}

}

/**

* 將px值轉換為sp值,保證文字大小不變

*/

public static float px2sp(Context context, float pxValue) {

float fontScale = context。getResources()。getDisplayMetrics()。scaledDensity;

return (pxValue / fontScale);

}

}

主要的區別在於:TextPaint的方法:measureText(text) descent ascent!

作者:小空和小芝中的小空

轉載說明:務必註明來源:

https://www。

zhihu。com/people/zhimal

ier

謝謝你看到這裡,如果對你有幫助的話,點個贊再走吧!

關注我 @空名先生

『更多專欄』:

有意思又酷的網站網址​www。zhihu。com/column/c_1223552298586140672​www。zhihu。com/column/c_1223552298586140672精緻神器軟體推薦​www。zhihu。com/column/c_1115315026340405248​www。zhihu。com/column/c_1115315026340405248精品書籍圖譜​www。zhihu。com/column/c_1318553820582780928​www。zhihu。com/column/c_1318553820582780928