如果接触过原生开发的朋友可能知道
最初几年官方推荐使用 sp 作为字体大小的单位,但是事实上经过长时间实践的情况下,大家都开始逐渐使用 dp 作为单位
这样使用者调整系统字体大小,app 中的文字大小就不会收到影响,出现错误等情况
iOS 中叫动态字体大小,对应辅助功能中的字体大小
android 中叫字体大小
当你开发完成,又遇到用户修改系统字体大小导致某些地方错位,甚至按钮被挤出屏幕看不见了就是个问题了
而 flutter 中没有单位的概念,我们应该如何实现这个功能呢
在 flutter 中,是由 MediaQuery 来实现对应功能的
var data = MediaQuery.of(context);
data.textScaleFactor; //这个就是对应的动态字体大小,我们只需要『修改』这个值就可以了
修改自然是不可能的,这东西都是 final 的,我们要做的就是 flutter 中的通用做法
class NoScaleTextWidget extends StatelessWidget {
final Widget child;
const NoScaleTextWidget({
Key key,
@required this.child,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaxScaleTextWidget(
max: 1.0,
child: child,
);
}
}
class MaxScaleTextWidget extends StatelessWidget {
final double max;
final Widget child;
const MaxScaleTextWidget({
Key key,
this.max = 1.2,
@required this.child,
}) : super(key: key);
@override
Widget build(BuildContext context) {
var data = MediaQuery.of(context);
var scale = math.min(max, data.textScaleFactor);
return MediaQuery(
data: data.copyWith(textScaleFactor: scale),
child: child,
);
}
}
我这里的做法就是这样,创建一个组件,在内部修改这个值,然后把你的控件『包』起来
这里可以是你的 Scaffold,Text 等等的 widget
不过这样要修改的地方太多,而且后面不好改
我们可以用一个小技巧,使用 MaterialApp 的 builder 属性
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State {
@override
Widget build(BuildContext context) {
return MaterialApp(
....
builder: (ctx, w) {
return MaxScaleTextWidget(
max: 1.0,
child: w,
);
},
);
}
}
在这个 builder 中这么写,就可以修改你 app 中的所有控件不受动态字体大小的影响了
我在 github 有一个 gisthttps://gist.github.com/CaiJingLong/d28208f569b44f39dd572a7e8f455912
也可查看到代码,需要自备梯子
动态字体的事情就是这样了