在Flutter中正確處理文本縮放的解決方案
本教程的結(jié)構(gòu)首先介紹最簡(jiǎn)單且最有影響力的解決方案。后面的部分涵蓋了較難實(shí)施且總體影響較小的解決方案,但它們對(duì)于解決特定情況很有用。

限制文本縮放的可能范圍
您可以為 MaterialApp 設(shè)置最小和最大縮放系數(shù),這將確保所有文本在指定范圍內(nèi)縮放。更小的界限需要更少的努力來(lái)保持可讀性和美觀(guān)性。不過(guò),邊界的選擇應(yīng)取決于目標(biāo)受眾。例如,如果您的應(yīng)用程序是為老年用戶(hù)設(shè)計(jì)的,您應(yīng)該考慮使用較寬松的邊界來(lái)滿(mǎn)足他們的需求。
MaterialApp(
...
builder: (_, child) => MediaQuery(
data: MediaQuery.of(context).copyWith(
textScaler: MediaQuery.of(context)
.textScaler
.clamp(minScaleFactor: 0.8, maxScaleFactor: 1.6),
),
child: child!,
),
);
不要對(duì)包含文本的元素使用固定高度
看一下這段代碼:
//不要這樣做
SizedBox(
height: 100,
child: Card(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Title", style: TextStyle(fontSize: 30), maxLines: 1),
Text("Subtitle", maxLines: 1),
],
),
),
),
),
可能會(huì)出現(xiàn)什么問(wèn)題?
正如您可能已經(jīng)猜到的,增加文本大小可能會(huì)導(dǎo)致 SizedBox 的內(nèi)容占用過(guò)多空間。

更好的解決方案是根據(jù)內(nèi)容高度和填充來(lái)設(shè)置項(xiàng)目的高度。此外,您可以使用 ConstrainedBox 設(shè)置最小高度。
ConstrainedBox(
constraints: const BoxConstraints(minHeight: 100),
child: const Card(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text("Title", style: TextStyle(fontSize: 30), maxLines: 1),
Text("Subtitle", maxLines: 1),
],
),
),
),
),
因此,在 100% 比例下,我們得到了一個(gè)相同的布局,而在 160% 比例下,我們得到了一個(gè)有效的布局。

這同樣適用于 ListView,如果您使用 itemExtent,請(qǐng)考慮使用字體比例計(jì)算或提供一個(gè) prototypeItem。
讓我們繼續(xù),想象一下這樣的布局:

項(xiàng)目 A 來(lái)自上一個(gè)示例。項(xiàng)目 B 有一些填充,應(yīng)該也能處理增加的文本縮放。屏幕底部有足夠的空間。那么,可能會(huì)出什么問(wèn)題呢?

不要忘記屏幕較小的手機(jī)。此外,當(dāng)語(yǔ)言發(fā)生變化時(shí),文本長(zhǎng)度也會(huì)發(fā)生變化。
確保內(nèi)容可滾動(dòng)
首先,我們應(yīng)該消除任何溢出,以確保我們的用戶(hù)可以訪(fǎng)問(wèn)所有內(nèi)容。添加一個(gè)簡(jiǎn)單的 SingleChildScrollView 將解決這個(gè)問(wèn)題。
考慮對(duì)邊距和填充使用自適應(yīng)值
這可能是一個(gè)有爭(zhēng)議的方法,但想象一下您自己是一個(gè)需要使用更大字體的用戶(hù)。您希望看到大量未使用的空間還是清楚地閱讀文本?
讓我們使用取決于邏輯像素?cái)?shù)的值來(lái)顯示文本。您可以將 smallScreenThreshold 調(diào)整為任何對(duì)您的應(yīng)用程序最合理的值。
class Dimens {
static const smallScreenThreshold = 300;
static bool isSmallWidth(BuildContext context) {
return MediaQuery.of(context).size.width /
MediaQuery.textScalerOf(context).scale(1) <
smallScreenThreshold;
}
static double small(BuildContext context) => isSmallWidth(context) ? 4 : 8;
static double medium(BuildContext context) => isSmallWidth(context) ? 8 : 16;
static double large(BuildContext context) => isSmallWidth(context) ? 16 : 32;
}
請(qǐng)注意,如果您想遵循人機(jī)界面指南和 Material Design,這些值應(yīng)能被 4 整除。
基于這些 Dimens 我們可以為插圖創(chuàng)建一個(gè)類(lèi):
class Insets {
static EdgeInsets small(BuildContext context) =>
EdgeInsets.all(Dimens.small(context));
static EdgeInsets medium(BuildContext context) =>
EdgeInsets.all(Dimens.medium(context));
static EdgeInsets large(BuildContext context) =>
EdgeInsets.all(Dimens.large(context));
}
在代碼中我們將其替換為:
//padding: const EdgeInsets.all(16), padding: Insets.medium(context), //SizedBox(height: 16), SizedBox(height: Dimens.medium(context)),
結(jié)果,我們贏得了更多的空間來(lái)在屏幕上繪制文本:

限制標(biāo)題文字大小的擴(kuò)展范圍
增加字體比例的主要目的是使視力下降的人能夠閱讀內(nèi)容。但是,應(yīng)用程序的某些部分(例如標(biāo)題)由于字體較大,可能已經(jīng)可以訪(fǎng)問(wèn)。為了解決這個(gè)問(wèn)題,我們可以限制文本可以放大的程度。實(shí)現(xiàn)此目的的一種方法是為標(biāo)題創(chuàng)建自定義小部件:
class TitleText extends StatelessWidget {
final String text;
final TextStyle style;
const TitleText(this.text, {required this.style, super.key});
static const double maxRealFontSize = 30;
@override
Widget build(BuildContext context) {
if (MediaQuery.textScalerOf(context).scale(style.fontSize!) >
maxRealFontSize) {
return Text(
text,
style: style.copyWith(
fontSize: maxRealFontSize / MediaQuery.textScalerOf(context).scale(1),
),
);
}
return Text(text, style: style);
}
}
通過(guò)這樣做,我們可以在不失去可讀性的情況下贏得更多空間。您可以將該 maxRealFontSize 更改為更適合您的應(yīng)用的任何值。

指定最大行數(shù)和文本溢出
不要忘記,某些文本在正常文本比例的大屏幕上可能看起來(lái)不錯(cuò),但在某些其他條件下可能會(huì)占用更多的垂直空間,但您并不總是需要顯示其完整內(nèi)容,例如字幕。只需將 maxLines 值添加到文本小部件即可。

使用字符串的替代版本
但并不總是能夠以仍然包含有用信息的方式縮短字符串。此外,不同語(yǔ)言的詞序也不同。英語(yǔ)中的第一個(gè)單詞可能位于另一種語(yǔ)言的句子末尾。讓我們考慮這個(gè)國(guó)際化 (i18n) 字符串的示例:
"tasksDone": {
"one": "You have done $completed of $n tasks",
"other": "You have done $completed of $n tasks"
},
"tasksDoneShort": {
"one": "$completed/$n tasks done",
"other": "$completed/$n tasks done"
},
最有意義的部分是顯示數(shù)字的部分。在較短的版本中,我們把它放在開(kāi)頭,使整個(gè)字符串更短。在代碼中,你可以這樣使用它:
Text(
Dimens.isSmallWidth(context)
? t.tasksDoneShort(n: 10, completed: 5)
: t.tasksDone(n: 10, completed: 5),
maxLines: 1,
)

正如您在屏幕截圖中看到的,縮短的版本有助于顯示所需的信息。
以上就是在Flutter中正確處理文本縮放的解決方案的詳細(xì)內(nèi)容,更多關(guān)于Flutter處理文本縮放的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
解決Android使用Handler造成內(nèi)存泄露問(wèn)題
內(nèi)存泄露的危害就是會(huì)使虛擬機(jī)占用內(nèi)存過(guò)高,導(dǎo)致OOM(內(nèi)存溢出),程序出錯(cuò)。接下來(lái)通過(guò)本文給大家分享Android使用Handler造成內(nèi)存泄露問(wèn)題及解決方法,一起看看吧2017-08-08
Android面試Intent采用了什么設(shè)計(jì)模式解析
這篇文章主要為大家介紹了Android面試Intent采用了什么設(shè)計(jì)模式解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03
Android Jetpack架構(gòu)組件 ViewModel詳解
這篇文章主要介紹了Android Jetpack架構(gòu)組件 ViewModel詳解,ViewModel類(lèi)讓數(shù)據(jù)可在發(fā)生屏幕旋轉(zhuǎn)等配置更改后繼續(xù)存在,ViewModel類(lèi)旨在以注重生命周期的方式存儲(chǔ)和管理界面相關(guān)的數(shù)據(jù)。感興趣可以來(lái)學(xué)習(xí)一下2020-07-07
Android總結(jié)之WebView與Javascript交互(互相調(diào)用)
本篇文章主要介紹了WebView與Javascript進(jìn)行數(shù)據(jù)交互,詳解的講訴了WebView與Javascript進(jìn)行數(shù)據(jù)交互的方法,有興趣的可以了解一下。2016-11-11
Android實(shí)現(xiàn)輕量線(xiàn)性與百分比圖表的方法
這篇文章主要給大家介紹了關(guān)于Android實(shí)現(xiàn)輕量線(xiàn)性與百分比圖表的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)學(xué)習(xí)吧。2017-12-12
Android WebView如何判定網(wǎng)頁(yè)加載的錯(cuò)誤
這篇文章主要介紹了Android WebView如何判定網(wǎng)頁(yè)加載的錯(cuò)誤,幫助大家更好的理解和學(xué)習(xí)使用Android,感興趣的朋友可以了解下2021-04-04

