Add framework support for system text scale factor. (#12180)
* Add framework-side support for system text scale factor.
* Rolling engine to e3404b81a53ba3180c7623a6f2190ebb28518f30
Additional changes rolled in with engine change:
libtxt: implementation of GetRectsForRange that processes a line at a time - e3404b8
Provide an entropy source to the Dart engine (#4161) - e1aa867
libtxt: search for fallback fonts that can match emoji and CJK characters - 8061df1
Roll skia to e4679fa06a. (#4157) - 267e7a8
Update buildroot to 53fea9aebbcc39c6522731471a1a45960ee0685e (#4160) - 02ea7ae
Revert engine Dart roll. (#4158) - 14aab33
Add support for system text scale factor. (#4124) - b2a7f4b
Include _http into sky_engine libraries for analyzer (#4154) - b930f10
libtxt: Remove postprocess_line and improve tracking of X offsets - 86f95f0
libtxt: remove redundant line_widths (#4152) - 14bf515
Roll dart to ade37f931e90b0fdb8fe16d6bf6f089545da55b6 (#4151) - 6f1264f
This commit is contained in:
@@ -1 +1 @@
|
||||
bdfedcc26f78ea332cdac0ed67590157c82c954e
|
||||
e3404b81a53ba3180c7623a6f2190ebb28518f30
|
||||
@@ -7,7 +7,7 @@
|
||||
<activity android:name="io.flutter.app.FlutterActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@android:style/Theme.Black.NoTitleBar"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<activity android:name="io.flutter.app.FlutterActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@android:style/Theme.Black.NoTitleBar"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<activity android:name=".MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@android:style/Theme.Black.NoTitleBar"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<activity android:name="com.yourcompany.platforminteraction.MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@android:style/Theme.Black.NoTitleBar"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
<activity android:name=".MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@android:style/Theme.Black.NoTitleBar"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<activity android:name=".MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@android:style/Theme.Black.NoTitleBar"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<activity android:name=".MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@android:style/Theme.Black.NoTitleBar"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<activity android:name=".MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@android:style/Theme.Light.NoTitleBar"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<activity android:name=".MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/Theme.AppCompat"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<activity android:name=".MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@android:style/Theme.Black.NoTitleBar"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<activity android:name=".MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@android:style/Theme.Black.NoTitleBar"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<activity android:name=".MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@android:style/Theme.Black.NoTitleBar"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
android:name="io.flutter.examples.platform_view.MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@android:style/Theme.Black.NoTitleBar"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
@@ -32,6 +32,6 @@
|
||||
android:name="io.flutter.examples.platform_view.CountActivity"
|
||||
android:parentActivityName="io.flutter.examples.platform_view.MainActivity"
|
||||
android:theme="@style/Theme.AppCompat.NoActionBar"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"></activity>
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale"></activity>
|
||||
</application>
|
||||
</manifest>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<activity android:name=".MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@android:style/Theme.Black.NoTitleBar"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<intent-filter>
|
||||
|
||||
@@ -245,8 +245,14 @@ class TextStyle extends Diagnosticable {
|
||||
/// During painting, the [fontSize] is multiplied by the current
|
||||
/// `textScaleFactor` to let users make it easier to read text by increasing
|
||||
/// its size.
|
||||
///
|
||||
/// [getParagraphStyle] will default to 14 logical pixels if the font size
|
||||
/// isn't specified here.
|
||||
final double fontSize;
|
||||
|
||||
// The default font size if none is specified.
|
||||
static const double _defaultFontSize = 14.0;
|
||||
|
||||
/// The typeface thickness to use when painting the text (e.g., bold).
|
||||
final FontWeight fontWeight;
|
||||
|
||||
@@ -444,6 +450,9 @@ class TextStyle extends Diagnosticable {
|
||||
/// The `textScaleFactor` argument must not be null. If omitted, it defaults
|
||||
/// to 1.0. The other arguments may be null. The `maxLines` argument, if
|
||||
/// specified and non-null, must be greater than zero.
|
||||
///
|
||||
/// If the font size on this style isn't set, it will default to 14 logical
|
||||
/// pixels.
|
||||
ui.ParagraphStyle getParagraphStyle({
|
||||
TextAlign textAlign,
|
||||
TextDirection textDirection,
|
||||
@@ -459,7 +468,7 @@ class TextStyle extends Diagnosticable {
|
||||
fontWeight: fontWeight,
|
||||
fontStyle: fontStyle,
|
||||
fontFamily: fontFamily,
|
||||
fontSize: fontSize == null ? null : fontSize * textScaleFactor,
|
||||
fontSize: (fontSize ?? _defaultFontSize) * textScaleFactor,
|
||||
lineHeight: height,
|
||||
maxLines: maxLines,
|
||||
ellipsis: ellipsis,
|
||||
|
||||
@@ -36,6 +36,7 @@ abstract class RendererBinding extends BindingBase with SchedulerBinding, Servic
|
||||
);
|
||||
ui.window
|
||||
..onMetricsChanged = handleMetricsChanged
|
||||
..onTextScaleFactorChanged = handleTextScaleFactorChanged
|
||||
..onSemanticsEnabledChanged = _handleSemanticsEnabledChanged
|
||||
..onSemanticsAction = _handleSemanticsAction;
|
||||
initRenderView();
|
||||
@@ -143,6 +144,11 @@ abstract class RendererBinding extends BindingBase with SchedulerBinding, Servic
|
||||
renderView.configuration = createViewConfiguration();
|
||||
}
|
||||
|
||||
/// Called when the platform text scale factor changes.
|
||||
///
|
||||
/// See [Window.onTextScaleFactorChanged].
|
||||
void handleTextScaleFactorChanged() { }
|
||||
|
||||
/// Returns a [ViewConfiguration] configured for the [RenderView] based on the
|
||||
/// current environment.
|
||||
///
|
||||
|
||||
@@ -398,6 +398,15 @@ class _WidgetsAppState extends State<WidgetsApp> implements WidgetsBindingObserv
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeTextScaleFactor() {
|
||||
setState(() {
|
||||
// The textScaleFactor property of ui.window has changed. We reference
|
||||
// ui.window in our build function, so we need to call setState(), but
|
||||
// we don't need to cache anything locally.
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void didChangeLocale(Locale locale) {
|
||||
if (locale == _locale)
|
||||
|
||||
@@ -90,7 +90,7 @@ abstract class WidgetsBindingObserver {
|
||||
/// navigator.
|
||||
///
|
||||
/// Observers are expected to return true if they were able to
|
||||
/// handle the notification. Observers are notified in registration
|
||||
/// handle the notification. Observers are notified in registration
|
||||
/// order until one returns true.
|
||||
Future<bool> didPushRoute(String route) => new Future<bool>.value(false);
|
||||
|
||||
@@ -133,7 +133,7 @@ abstract class WidgetsBindingObserver {
|
||||
///
|
||||
/// @override
|
||||
/// Widget build(BuildContext context) {
|
||||
/// return new Text('Last size: $_lastSize');
|
||||
/// return new Text('Current size: $_lastSize');
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
@@ -148,6 +148,55 @@ abstract class WidgetsBindingObserver {
|
||||
/// boilerplate.
|
||||
void didChangeMetrics() { }
|
||||
|
||||
/// Called when the platform's text scale factor changes.
|
||||
///
|
||||
/// This typically happens as the result of the user changing system
|
||||
/// preferences, and it should affect all of the text sizes in the
|
||||
/// application.
|
||||
///
|
||||
/// ## Sample code
|
||||
///
|
||||
/// ```dart
|
||||
/// class TextScaleFactorReactor extends StatefulWidget {
|
||||
/// const TextScaleFactorReactor({ Key key }) : super(key: key);
|
||||
///
|
||||
/// @override
|
||||
/// _TextScaleFactorReactorState createState() => new _TextScaleFactorReactorState();
|
||||
/// }
|
||||
///
|
||||
/// class _TextScaleFactorReactorState extends State<TextScaleFactorReactor> with WidgetsBindingObserver {
|
||||
/// @override
|
||||
/// void initState() {
|
||||
/// super.initState();
|
||||
/// WidgetsBinding.instance.addObserver(this);
|
||||
/// }
|
||||
///
|
||||
/// @override
|
||||
/// void dispose() {
|
||||
/// WidgetsBinding.instance.removeObserver(this);
|
||||
/// super.dispose();
|
||||
/// }
|
||||
///
|
||||
/// double _lastTextScaleFactor;
|
||||
///
|
||||
/// @override
|
||||
/// void didChangeTextScaleFactor() {
|
||||
/// setState(() { _lastTextScaleFactor = ui.window.textScaleFactor; });
|
||||
/// }
|
||||
///
|
||||
/// @override
|
||||
/// Widget build(BuildContext context) {
|
||||
/// return new Text('Current scale factor: $_lastTextScaleFactor');
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// See also:
|
||||
///
|
||||
/// * [MediaQuery.of], which provides a similar service with less
|
||||
/// boilerplate.
|
||||
void didChangeTextScaleFactor() { }
|
||||
|
||||
/// Called when the system tells the app that the user's locale has
|
||||
/// changed. For example, if the user changes the system language
|
||||
/// settings.
|
||||
@@ -284,12 +333,6 @@ abstract class WidgetsBinding extends BindingBase with GestureBinding, RendererB
|
||||
/// * [WidgetsBindingObserver], which has an example of using this method.
|
||||
bool removeObserver(WidgetsBindingObserver observer) => _observers.remove(observer);
|
||||
|
||||
/// Called when the system metrics change.
|
||||
///
|
||||
/// Notifies all the observers using
|
||||
/// [WidgetsBindingObserver.didChangeMetrics].
|
||||
///
|
||||
/// See [Window.onMetricsChanged].
|
||||
@override
|
||||
void handleMetricsChanged() {
|
||||
super.handleMetricsChanged();
|
||||
@@ -297,6 +340,13 @@ abstract class WidgetsBinding extends BindingBase with GestureBinding, RendererB
|
||||
observer.didChangeMetrics();
|
||||
}
|
||||
|
||||
@override
|
||||
void handleTextScaleFactorChanged() {
|
||||
super.handleTextScaleFactorChanged();
|
||||
for (WidgetsBindingObserver observer in _observers)
|
||||
observer.didChangeTextScaleFactor();
|
||||
}
|
||||
|
||||
/// Called when the system locale changes.
|
||||
///
|
||||
/// Calls [dispatchLocaleChanged] to notify the binding observers.
|
||||
|
||||
@@ -52,7 +52,7 @@ class MediaQueryData {
|
||||
MediaQueryData.fromWindow(ui.Window window)
|
||||
: size = window.physicalSize / window.devicePixelRatio,
|
||||
devicePixelRatio = window.devicePixelRatio,
|
||||
textScaleFactor = 1.0, // TODO(abarth): Read this value from window.
|
||||
textScaleFactor = window.textScaleFactor,
|
||||
padding = new EdgeInsets.fromWindowPadding(window.padding, window.devicePixelRatio);
|
||||
|
||||
/// The size of the media in logical pixel (e.g, the size of the screen).
|
||||
@@ -147,7 +147,10 @@ class MediaQueryData {
|
||||
int get hashCode => hashValues(size, devicePixelRatio, textScaleFactor, padding);
|
||||
|
||||
@override
|
||||
String toString() => '$runtimeType(size: $size, devicePixelRatio: $devicePixelRatio, textScaleFactor: $textScaleFactor, padding: $padding)';
|
||||
String toString() {
|
||||
return '$runtimeType(size: $size, devicePixelRatio: $devicePixelRatio, '
|
||||
'textScaleFactor: $textScaleFactor, padding: $padding)';
|
||||
}
|
||||
}
|
||||
|
||||
/// Establishes a subtree in which media queries resolve to the given data.
|
||||
|
||||
@@ -249,7 +249,8 @@ class Text extends StatelessWidget {
|
||||
/// For example, if the text scale factor is 1.5, text will be 50% larger than
|
||||
/// the specified font size.
|
||||
///
|
||||
/// Defaults to the [MediaQueryData.textScaleFactor] obtained from the ambient
|
||||
/// The value given to the constructor as textScaleFactor. If null, will
|
||||
/// use the [MediaQueryData.textScaleFactor] obtained from the ambient
|
||||
/// [MediaQuery], or 1.0 if there is no [MediaQuery] in scope.
|
||||
final double textScaleFactor;
|
||||
|
||||
|
||||
@@ -305,4 +305,16 @@ void main() {
|
||||
expect(tester.takeException(), isFlutterError);
|
||||
expect(log, <String>['onGenerateRoute /', 'onUnknownRoute /']);
|
||||
});
|
||||
|
||||
testWidgets('Can get text scale from media query', (WidgetTester tester) async {
|
||||
double textScaleFactor;
|
||||
await tester.pumpWidget(new MaterialApp(
|
||||
home: new Builder(builder:(BuildContext context) {
|
||||
textScaleFactor = MediaQuery.of(context).textScaleFactor;
|
||||
return new Container();
|
||||
}),
|
||||
));
|
||||
expect(textScaleFactor, isNotNull);
|
||||
expect(textScaleFactor, equals(1.0));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -44,6 +44,46 @@ void main() {
|
||||
semantics.dispose();
|
||||
});
|
||||
|
||||
testWidgets('Does FlatButton scale with font scale changes', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
new Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: new Material(
|
||||
child: new MediaQuery(
|
||||
data: const MediaQueryData(textScaleFactor: 1.0),
|
||||
child: new Center(
|
||||
child: new FlatButton(
|
||||
onPressed: () { },
|
||||
child: const Text('ABC'),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(tester.getSize(find.byType(FlatButton)), equals(const Size(88.0, 36.0)));
|
||||
|
||||
await tester.pumpWidget(
|
||||
new Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: new Material(
|
||||
child: new MediaQuery(
|
||||
data: const MediaQueryData(textScaleFactor: 1.3),
|
||||
child: new Center(
|
||||
child: new FlatButton(
|
||||
onPressed: () { },
|
||||
child: const Text('ABC'),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
expect(tester.getSize(find.byType(FlatButton)), equals(const Size(88.0, 36.0)));
|
||||
});
|
||||
|
||||
// This test is very similar to the '...explicit splashColor and highlightColor' test
|
||||
// in icon_button_test.dart. If you change this one, you may want to also change that one.
|
||||
testWidgets('MaterialButton with explicit splashColor and highlightColor', (WidgetTester tester) async {
|
||||
|
||||
@@ -57,6 +57,23 @@ void main() {
|
||||
expect(painter.size, const Size(123.0, 123.0));
|
||||
});
|
||||
|
||||
test('TextPainter textScaleFactor test', () {
|
||||
final TextPainter painter = new TextPainter(
|
||||
text: const TextSpan(
|
||||
text: 'X',
|
||||
style: const TextStyle(
|
||||
inherit: false,
|
||||
fontFamily: 'Ahem',
|
||||
fontSize: 10.0,
|
||||
),
|
||||
),
|
||||
textDirection: TextDirection.ltr,
|
||||
textScaleFactor: 2.0,
|
||||
);
|
||||
painter.layout();
|
||||
expect(painter.size, const Size(20.0, 20.0));
|
||||
});
|
||||
|
||||
test('TextPainter default text height is 14 pixels', () {
|
||||
final TextPainter painter = new TextPainter(
|
||||
text: const TextSpan(text: 'x'),
|
||||
|
||||
@@ -125,12 +125,12 @@ void main() {
|
||||
|
||||
test('TextStyle with text direction', () {
|
||||
final ui.ParagraphStyle ps6 = const TextStyle().getParagraphStyle(textDirection: TextDirection.ltr);
|
||||
expect(ps6, equals(new ui.ParagraphStyle(textDirection: TextDirection.ltr)));
|
||||
expect(ps6.toString(), 'ParagraphStyle(textAlign: unspecified, textDirection: TextDirection.ltr, fontWeight: unspecified, fontStyle: unspecified, maxLines: unspecified, fontFamily: unspecified, fontSize: unspecified, lineHeight: unspecified, ellipsis: unspecified)');
|
||||
expect(ps6, equals(new ui.ParagraphStyle(textDirection: TextDirection.ltr, fontSize: 14.0)));
|
||||
expect(ps6.toString(), 'ParagraphStyle(textAlign: unspecified, textDirection: TextDirection.ltr, fontWeight: unspecified, fontStyle: unspecified, maxLines: unspecified, fontFamily: unspecified, fontSize: 14.0, lineHeight: unspecified, ellipsis: unspecified)');
|
||||
|
||||
final ui.ParagraphStyle ps7 = const TextStyle().getParagraphStyle(textDirection: TextDirection.rtl);
|
||||
expect(ps7, equals(new ui.ParagraphStyle(textDirection: TextDirection.rtl)));
|
||||
expect(ps7.toString(), 'ParagraphStyle(textAlign: unspecified, textDirection: TextDirection.rtl, fontWeight: unspecified, fontStyle: unspecified, maxLines: unspecified, fontFamily: unspecified, fontSize: unspecified, lineHeight: unspecified, ellipsis: unspecified)');
|
||||
expect(ps7, equals(new ui.ParagraphStyle(textDirection: TextDirection.rtl, fontSize: 14.0)));
|
||||
expect(ps7.toString(), 'ParagraphStyle(textAlign: unspecified, textDirection: TextDirection.rtl, fontWeight: unspecified, fontStyle: unspecified, maxLines: unspecified, fontFamily: unspecified, fontSize: 14.0, lineHeight: unspecified, ellipsis: unspecified)');
|
||||
});
|
||||
|
||||
test('TextStyle using package font', () {
|
||||
|
||||
@@ -222,6 +222,64 @@ void main() {
|
||||
expect(paragraph.debugNeedsPaint, isFalse);
|
||||
});
|
||||
|
||||
test('nested TextSpans in paragraph handle textScaleFactor correctly.', () {
|
||||
final TextSpan testSpan = const TextSpan(
|
||||
text: 'a',
|
||||
style: const TextStyle(
|
||||
fontSize: 10.0,
|
||||
),
|
||||
children: const <TextSpan>[
|
||||
const TextSpan(
|
||||
text: 'b',
|
||||
children: const <TextSpan>[
|
||||
const TextSpan(text: 'c'),
|
||||
],
|
||||
style: const TextStyle(
|
||||
fontSize: 20.0,
|
||||
),
|
||||
),
|
||||
const TextSpan(
|
||||
text: 'd',
|
||||
),
|
||||
],
|
||||
);
|
||||
final RenderParagraph paragraph = new RenderParagraph(
|
||||
testSpan,
|
||||
textDirection: TextDirection.ltr,
|
||||
textScaleFactor: 1.3
|
||||
);
|
||||
paragraph.layout(const BoxConstraints());
|
||||
// anyOf is needed here because Linux and Mac have different text
|
||||
// rendering widths in tests.
|
||||
// TODO(#12357): Figure out why this is, and fix it (if needed) once Blink
|
||||
// text rendering is replaced.
|
||||
expect(paragraph.size.width, anyOf(79.0, 78.0));
|
||||
expect(paragraph.size.height, 26.0);
|
||||
|
||||
// Test the sizes of nested spans.
|
||||
final List<ui.TextBox> boxes = <ui.TextBox>[];
|
||||
final String text = testSpan.toStringDeep();
|
||||
for (int i = 0; i < text.length; ++i) {
|
||||
boxes.addAll(paragraph.getBoxesForSelection(
|
||||
new TextSelection(baseOffset: i, extentOffset: i + 1)
|
||||
));
|
||||
}
|
||||
expect(boxes.length, equals(4));
|
||||
|
||||
// anyOf is needed here and below because Linux and Mac have different text
|
||||
// rendering widths in tests.
|
||||
// TODO(#12357): Figure out why this is, and fix it (if needed) once Blink
|
||||
// text rendering is replaced.
|
||||
expect(boxes[0].toRect().width, anyOf(14.0, 13.0));
|
||||
expect(boxes[0].toRect().height, 13.0);
|
||||
expect(boxes[1].toRect().width, anyOf(27.0, 26.0));
|
||||
expect(boxes[1].toRect().height, 26.0);
|
||||
expect(boxes[2].toRect().width, anyOf(27.0, 26.0));
|
||||
expect(boxes[2].toRect().height, 26.0);
|
||||
expect(boxes[3].toRect().width, anyOf(14.0, 13.0));
|
||||
expect(boxes[3].toRect().height, 13.0);
|
||||
});
|
||||
|
||||
test('toStringDeep', () {
|
||||
final RenderParagraph paragraph = new RenderParagraph(
|
||||
const TextSpan(text: _kText),
|
||||
|
||||
@@ -8,7 +8,7 @@ import 'package:flutter/widgets.dart';
|
||||
void main() {
|
||||
testWidgets('Text respects media query', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(const MediaQuery(
|
||||
data: const MediaQueryData(textScaleFactor: 1.5),
|
||||
data: const MediaQueryData(textScaleFactor: 1.3),
|
||||
child: const Center(
|
||||
child: const Text('Hello', textDirection: TextDirection.ltr)
|
||||
)
|
||||
@@ -16,7 +16,7 @@ void main() {
|
||||
|
||||
RichText text = tester.firstWidget(find.byType(RichText));
|
||||
expect(text, isNotNull);
|
||||
expect(text.textScaleFactor, 1.5);
|
||||
expect(text.textScaleFactor, 1.3);
|
||||
|
||||
await tester.pumpWidget(const Center(
|
||||
child: const Text('Hello', textDirection: TextDirection.ltr)
|
||||
@@ -25,14 +25,58 @@ void main() {
|
||||
text = tester.firstWidget(find.byType(RichText));
|
||||
expect(text, isNotNull);
|
||||
expect(text.textScaleFactor, 1.0);
|
||||
});
|
||||
|
||||
testWidgets('Text respects textScaleFactor with default font size', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(
|
||||
const Center(child: const Text('Hello', textDirection: TextDirection.ltr))
|
||||
);
|
||||
|
||||
RichText text = tester.firstWidget(find.byType(RichText));
|
||||
expect(text, isNotNull);
|
||||
expect(text.textScaleFactor, 1.0);
|
||||
final Size baseSize = tester.getSize(find.byType(RichText));
|
||||
expect(baseSize.width, equals(70.0));
|
||||
expect(baseSize.height, equals(14.0));
|
||||
|
||||
await tester.pumpWidget(const Center(
|
||||
child: const Text('Hello', textScaleFactor: 3.0, textDirection: TextDirection.ltr)
|
||||
child: const Text('Hello', textScaleFactor: 1.5, textDirection: TextDirection.ltr)
|
||||
));
|
||||
|
||||
text = tester.firstWidget(find.byType(RichText));
|
||||
expect(text, isNotNull);
|
||||
expect(text.textScaleFactor, 3.0);
|
||||
expect(text.textScaleFactor, 1.5);
|
||||
final Size largeSize = tester.getSize(find.byType(RichText));
|
||||
expect(largeSize.width, 105.0);
|
||||
expect(largeSize.height, equals(21.0));
|
||||
});
|
||||
|
||||
testWidgets('Text respects textScaleFactor with explicit font size', (WidgetTester tester) async {
|
||||
await tester.pumpWidget(const Center(
|
||||
child: const Text('Hello',
|
||||
style: const TextStyle(fontSize: 20.0), textDirection: TextDirection.ltr)
|
||||
));
|
||||
|
||||
RichText text = tester.firstWidget(find.byType(RichText));
|
||||
expect(text, isNotNull);
|
||||
expect(text.textScaleFactor, 1.0);
|
||||
final Size baseSize = tester.getSize(find.byType(RichText));
|
||||
expect(baseSize.width, equals(100.0));
|
||||
expect(baseSize.height, equals(20.0));
|
||||
|
||||
await tester.pumpWidget(const Center(
|
||||
child: const Text('Hello',
|
||||
style: const TextStyle(fontSize: 20.0),
|
||||
textScaleFactor: 1.3,
|
||||
textDirection: TextDirection.ltr)
|
||||
));
|
||||
|
||||
text = tester.firstWidget(find.byType(RichText));
|
||||
expect(text, isNotNull);
|
||||
expect(text.textScaleFactor, 1.3);
|
||||
final Size largeSize = tester.getSize(find.byType(RichText));
|
||||
expect(largeSize.width, anyOf(131.0, 130.0));
|
||||
expect(largeSize.height, equals(26.0));
|
||||
});
|
||||
|
||||
testWidgets('Text throws a nice error message if there\'s no Directionality', (WidgetTester tester) async {
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
android:name=".MainActivity"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/LaunchTheme"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
|
||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<!-- This keeps the window background of the activity showing
|
||||
|
||||
Reference in New Issue
Block a user