I'm trying to use a GestureDetector
to allow the user to change the font size by pinching:
class _PinchToScaleFontState extends State<PinchToScaleFont> {
double _baseFontScale = 1;
double _fontScale = 1;
ThemeData _themeData;
@override
Widget build(BuildContext context) {
return GestureDetector(
child: Theme(
data: _themeData,
child: widget.child // The desired outcome is that all Text is resized
),
onScaleStart: (ScaleStartDetails scaleStartDetails) {
_baseFontScale = _fontScale;
},
onScaleUpdate: (ScaleUpdateDetails scaleUpdateDetails) {
// don't update the UI if the scale didn't change
if (scaleUpdateDetails.scale == 1.0) {
return;
}
setState(() {
double fontScale = (_baseFontScale * scaleUpdateDetails.scale).clamp(0.5, 5.0);
_updateFontScale(fontScale);
SharedPreferences.getInstance().then((prefs) => prefs.setDouble('fontScale', fontScale));
});
},
);
}
I can get the following code to adjust the scale of a TextField
, but it won't resize any Text
widgets.
_updateFontScale(double fontScale) {
setState(() {
_fontScale = fontScale;
ThemeData theme = Theme.of(context);
/// This doesn't seem to work at all
// _themeData = theme.copyWith(textTheme: theme.textTheme.merge(TextTheme(bodyText2: TextStyle(fontSize: 14 * fontScale))));
/// This works for `TextField` but not `Text`
_themeData = theme.copyWith(textTheme: theme.textTheme.apply(fontSizeFactor: fontScale)); // merge(TextTheme()));
});
// }
}
It's strange. In the code below I can use the saved fontScale to initialise the font size for the whole app the next time it's loaded, but why won't the code above, which seems to be accessing the same theme property give the same results?
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
double savedFontScale = (await SharedPreferences.getInstance()).getDouble('fontScale') ?? 1.0;
runApp(MyApp(savedFontScale));
}
class MyApp extends StatelessWidget {
final double fontScale;
MyApp(this.fontScale);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: APP_NAME,
theme: ThemeData(
textTheme: TextTheme(
/// This works for all `Text` widgets - but you've got to restart the app
bodyText2: TextStyle(fontSize: 14 * fontScale),
...
home:
...
PinchToScaleFont(
...
TextField('This _will_ resize '),
Text('This will not resize, but it should '),