Commit 2d949ab6 authored by Adam Barth's avatar Adam Barth Committed by GitHub

Improve RTL support (#12008)

Fix a bunch of obvious RTL bugs from code inspection.
parent 11de1a51
...@@ -61,7 +61,7 @@ class CupertinoButton extends StatefulWidget { ...@@ -61,7 +61,7 @@ class CupertinoButton extends StatefulWidget {
/// The amount of space to surround the child inside the bounds of the button. /// The amount of space to surround the child inside the bounds of the button.
/// ///
/// Defaults to 16.0 pixels. /// Defaults to 16.0 pixels.
final EdgeInsets padding; final EdgeInsetsGeometry padding;
/// The color of the button's background. /// The color of the button's background.
/// ///
......
...@@ -405,7 +405,7 @@ class _LicensePageState extends State<LicensePage> { ...@@ -405,7 +405,7 @@ class _LicensePageState extends State<LicensePage> {
} else { } else {
assert(paragraph.indent >= 0); assert(paragraph.indent >= 0);
_licenses.add(new Padding( _licenses.add(new Padding(
padding: new EdgeInsets.only(top: 8.0, left: 16.0 * paragraph.indent), padding: new EdgeInsetsDirectional.only(top: 8.0, start: 16.0 * paragraph.indent),
child: new Text(paragraph.text) child: new Text(paragraph.text)
)); ));
} }
......
...@@ -362,7 +362,7 @@ class DataTable extends StatelessWidget { ...@@ -362,7 +362,7 @@ class DataTable extends StatelessWidget {
ValueChanged<bool> onCheckboxChanged ValueChanged<bool> onCheckboxChanged
}) { }) {
Widget contents = new Padding( Widget contents = new Padding(
padding: const EdgeInsets.fromLTRB(_kTablePadding, 0.0, _kTablePadding / 2.0, 0.0), padding: const EdgeInsetsDirectional.only(start: _kTablePadding, end: _kTablePadding / 2.0),
child: new Center( child: new Center(
child: new Checkbox( child: new Checkbox(
activeColor: color, activeColor: color,
...@@ -385,7 +385,7 @@ class DataTable extends StatelessWidget { ...@@ -385,7 +385,7 @@ class DataTable extends StatelessWidget {
Widget _buildHeadingCell({ Widget _buildHeadingCell({
BuildContext context, BuildContext context,
EdgeInsets padding, EdgeInsetsGeometry padding,
Widget label, Widget label,
String tooltip, String tooltip,
bool numeric, bool numeric,
...@@ -408,7 +408,7 @@ class DataTable extends StatelessWidget { ...@@ -408,7 +408,7 @@ class DataTable extends StatelessWidget {
label = new Container( label = new Container(
padding: padding, padding: padding,
height: _kHeadingRowHeight, height: _kHeadingRowHeight,
alignment: new FractionalOffset(numeric ? 1.0 : 0.0, 0.5), // TODO(ianh): RTL for non-numeric alignment: numeric ? FractionalOffset.centerRight : FractionalOffsetDirectional.centerStart,
child: new AnimatedDefaultTextStyle( child: new AnimatedDefaultTextStyle(
style: new TextStyle( style: new TextStyle(
// TODO(ianh): font family should be Roboto; see https://github.com/flutter/flutter/issues/3116 // TODO(ianh): font family should be Roboto; see https://github.com/flutter/flutter/issues/3116
...@@ -441,7 +441,7 @@ class DataTable extends StatelessWidget { ...@@ -441,7 +441,7 @@ class DataTable extends StatelessWidget {
Widget _buildDataCell({ Widget _buildDataCell({
BuildContext context, BuildContext context,
EdgeInsets padding, EdgeInsetsGeometry padding,
Widget label, Widget label,
bool numeric, bool numeric,
bool placeholder, bool placeholder,
...@@ -458,7 +458,7 @@ class DataTable extends StatelessWidget { ...@@ -458,7 +458,7 @@ class DataTable extends StatelessWidget {
label = new Container( label = new Container(
padding: padding, padding: padding,
height: _kDataRowHeight, height: _kDataRowHeight,
alignment: new FractionalOffset(numeric ? 1.0 : 0.0, 0.5), // TODO(ianh): RTL for non-numeric alignment: numeric ? FractionalOffset.centerRight : FractionalOffsetDirectional.centerStart,
child: new DefaultTextStyle( child: new DefaultTextStyle(
style: new TextStyle( style: new TextStyle(
// TODO(ianh): font family should be Roboto; see https://github.com/flutter/flutter/issues/3116 // TODO(ianh): font family should be Roboto; see https://github.com/flutter/flutter/issues/3116
...@@ -544,11 +544,9 @@ class DataTable extends StatelessWidget { ...@@ -544,11 +544,9 @@ class DataTable extends StatelessWidget {
for (int dataColumnIndex = 0; dataColumnIndex < columns.length; dataColumnIndex += 1) { for (int dataColumnIndex = 0; dataColumnIndex < columns.length; dataColumnIndex += 1) {
final DataColumn column = columns[dataColumnIndex]; final DataColumn column = columns[dataColumnIndex];
final EdgeInsets padding = new EdgeInsets.fromLTRB( final EdgeInsetsDirectional padding = new EdgeInsetsDirectional.only(
dataColumnIndex == 0 ? showCheckboxColumn ? _kTablePadding / 2.0 : _kTablePadding : _kColumnSpacing / 2.0, start: dataColumnIndex == 0 ? showCheckboxColumn ? _kTablePadding / 2.0 : _kTablePadding : _kColumnSpacing / 2.0,
0.0, end: dataColumnIndex == columns.length - 1 ? _kTablePadding : _kColumnSpacing / 2.0,
dataColumnIndex == columns.length - 1 ? _kTablePadding : _kColumnSpacing / 2.0,
0.0
); );
if (dataColumnIndex == _onlyTextColumn) { if (dataColumnIndex == _onlyTextColumn) {
tableColumns[displayColumnIndex] = const IntrinsicColumnWidth(flex: 1.0); tableColumns[displayColumnIndex] = const IntrinsicColumnWidth(flex: 1.0);
......
...@@ -66,7 +66,7 @@ class Divider extends StatelessWidget { ...@@ -66,7 +66,7 @@ class Divider extends StatelessWidget {
child: new Center( child: new Center(
child: new Container( child: new Container(
height: 0.0, height: 0.0,
margin: new EdgeInsets.only(left: indent), margin: new EdgeInsetsDirectional.only(start: indent),
decoration: new BoxDecoration( decoration: new BoxDecoration(
border: new Border( border: new Border(
bottom: new BorderSide( bottom: new BorderSide(
......
...@@ -128,7 +128,7 @@ class ExpansionPanelList extends StatelessWidget { ...@@ -128,7 +128,7 @@ class ExpansionPanelList extends StatelessWidget {
) )
), ),
new Container( new Container(
margin: const EdgeInsets.only(right: 8.0), margin: const EdgeInsetsDirectional.only(end: 8.0),
child: new ExpandIcon( child: new ExpandIcon(
isExpanded: _isChildExpanded(i), isExpanded: _isChildExpanded(i),
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
......
...@@ -92,6 +92,20 @@ class _FlexibleSpaceBarState extends State<FlexibleSpaceBar> { ...@@ -92,6 +92,20 @@ class _FlexibleSpaceBarState extends State<FlexibleSpaceBar> {
return null; return null;
} }
FractionalOffset _getTitleAlignment(bool effectiveCenterTitle) {
if (effectiveCenterTitle)
return FractionalOffset.bottomCenter;
final TextDirection textDirection = Directionality.of(context);
assert(textDirection != null);
switch (textDirection) {
case TextDirection.rtl:
return FractionalOffset.bottomRight;
case TextDirection.ltr:
return FractionalOffset.bottomLeft;
}
return null;
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final _FlexibleSpaceBarSettings settings = context.inheritFromWidgetOfExactType(_FlexibleSpaceBarSettings); final _FlexibleSpaceBarSettings settings = context.inheritFromWidgetOfExactType(_FlexibleSpaceBarSettings);
...@@ -138,10 +152,10 @@ class _FlexibleSpaceBarState extends State<FlexibleSpaceBar> { ...@@ -138,10 +152,10 @@ class _FlexibleSpaceBarState extends State<FlexibleSpaceBar> {
final double scaleValue = new Tween<double>(begin: 1.5, end: 1.0).lerp(t); final double scaleValue = new Tween<double>(begin: 1.5, end: 1.0).lerp(t);
final Matrix4 scaleTransform = new Matrix4.identity() final Matrix4 scaleTransform = new Matrix4.identity()
..scale(scaleValue, scaleValue, 1.0); ..scale(scaleValue, scaleValue, 1.0);
final FractionalOffset titleAlignment = effectiveCenterTitle ? FractionalOffset.bottomCenter : FractionalOffset.bottomLeft; final FractionalOffset titleAlignment = _getTitleAlignment(effectiveCenterTitle);
children.add(new Container( children.add(new Container(
padding: new EdgeInsets.only( padding: new EdgeInsetsDirectional.only(
left: effectiveCenterTitle ? 0.0 : 72.0, start: effectiveCenterTitle ? 0.0 : 72.0,
bottom: 16.0 bottom: 16.0
), ),
child: new Transform( child: new Transform(
......
...@@ -288,7 +288,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> { ...@@ -288,7 +288,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
final ThemeData themeData = Theme.of(context); final ThemeData themeData = Theme.of(context);
// HEADER // HEADER
final List<Widget> headerWidgets = <Widget>[]; final List<Widget> headerWidgets = <Widget>[];
double leftPadding = 24.0; double startPadding = 24.0;
if (_selectedRowCount == 0) { if (_selectedRowCount == 0) {
headerWidgets.add(new Expanded(child: widget.header)); headerWidgets.add(new Expanded(child: widget.header));
if (widget.header is ButtonBar) { if (widget.header is ButtonBar) {
...@@ -298,7 +298,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> { ...@@ -298,7 +298,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
// pixels internally on each side, yet we want the left edge of the // pixels internally on each side, yet we want the left edge of the
// inside of the button to line up with the 24.0 left inset. // inside of the button to line up with the 24.0 left inset.
// TODO(ianh): Better magic. See https://github.com/flutter/flutter/issues/4460 // TODO(ianh): Better magic. See https://github.com/flutter/flutter/issues/4460
leftPadding = 12.0; startPadding = 12.0;
} }
} else if (_selectedRowCount == 1) { } else if (_selectedRowCount == 1) {
// TODO(ianh): Real l10n. // TODO(ianh): Real l10n.
...@@ -311,7 +311,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> { ...@@ -311,7 +311,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
widget.actions.map<Widget>((Widget action) { widget.actions.map<Widget>((Widget action) {
return new Padding( return new Padding(
// 8.0 is the default padding of an icon button // 8.0 is the default padding of an icon button
padding: const EdgeInsets.only(left: 24.0 - 8.0 * 2.0), padding: const EdgeInsetsDirectional.only(start: 24.0 - 8.0 * 2.0),
child: action, child: action,
); );
}).toList() }).toList()
...@@ -384,7 +384,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> { ...@@ -384,7 +384,7 @@ class PaginatedDataTableState extends State<PaginatedDataTable> {
child: new ButtonTheme.bar( child: new ButtonTheme.bar(
child: new Container( child: new Container(
height: 64.0, height: 64.0,
padding: new EdgeInsets.fromLTRB(leftPadding, 0.0, 14.0, 0.0), padding: new EdgeInsetsDirectional.only(start: startPadding, end: 14.0),
// TODO(ianh): This decoration will prevent ink splashes from being visible. // TODO(ianh): This decoration will prevent ink splashes from being visible.
// Instead, we should have a widget that prints the decoration on the material. // Instead, we should have a widget that prints the decoration on the material.
// See https://github.com/flutter/flutter/issues/3782 // See https://github.com/flutter/flutter/issues/3782
......
...@@ -707,7 +707,7 @@ class PopupMenuButton<T> extends StatefulWidget { ...@@ -707,7 +707,7 @@ class PopupMenuButton<T> extends StatefulWidget {
/// Matches IconButton's 8 dps padding by default. In some cases, notably where /// Matches IconButton's 8 dps padding by default. In some cases, notably where
/// this button appears as the trailing element of a list item, it's useful to be able /// this button appears as the trailing element of a list item, it's useful to be able
/// to set the padding to zero. /// to set the padding to zero.
final EdgeInsets padding; final EdgeInsetsGeometry padding;
/// If provided, the widget used for this button. /// If provided, the widget used for this button.
final Widget child; final Widget child;
......
...@@ -954,7 +954,7 @@ class _PersistentBottomSheetState extends State<_PersistentBottomSheet> { ...@@ -954,7 +954,7 @@ class _PersistentBottomSheetState extends State<_PersistentBottomSheet> {
animation: widget.animationController, animation: widget.animationController,
builder: (BuildContext context, Widget child) { builder: (BuildContext context, Widget child) {
return new Align( return new Align(
alignment: FractionalOffset.topLeft, alignment: FractionalOffsetDirectional.topStart,
heightFactor: widget.animationController.value, heightFactor: widget.animationController.value,
child: child child: child
); );
......
...@@ -222,7 +222,7 @@ class SnackBar extends StatelessWidget { ...@@ -222,7 +222,7 @@ class SnackBar extends StatelessWidget {
animation: heightAnimation, animation: heightAnimation,
builder: (BuildContext context, Widget child) { builder: (BuildContext context, Widget child) {
return new Align( return new Align(
alignment: FractionalOffset.topLeft, alignment: FractionalOffsetDirectional.topStart,
heightFactor: heightAnimation.value, heightFactor: heightAnimation.value,
child: child child: child
); );
......
...@@ -26,13 +26,13 @@ class _AccountPictures extends StatelessWidget { ...@@ -26,13 +26,13 @@ class _AccountPictures extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return new Stack( return new Stack(
children: <Widget>[ children: <Widget>[
new Positioned( new PositionedDirectional(
top: 0.0, top: 0.0,
right: 0.0, end: 0.0,
child: new Row( child: new Row(
children: (otherAccountsPictures ?? <Widget>[]).take(3).map((Widget picture) { children: (otherAccountsPictures ?? <Widget>[]).take(3).map((Widget picture) {
return new Container( return new Container(
margin: const EdgeInsets.only(left: 16.0), margin: const EdgeInsetsDirectional.only(start: 16.0),
width: 40.0, width: 40.0,
height: 40.0, height: 40.0,
child: picture child: picture
...@@ -70,7 +70,7 @@ class _AccountDetails extends StatelessWidget { ...@@ -70,7 +70,7 @@ class _AccountDetails extends StatelessWidget {
Widget addDropdownIcon(Widget line) { Widget addDropdownIcon(Widget line) {
final Widget icon = new Expanded( final Widget icon = new Expanded(
child: new Align( child: new Align(
alignment: FractionalOffset.centerRight, alignment: FractionalOffsetDirectional.centerEnd,
child: new Icon( child: new Icon(
isOpen ? Icons.arrow_drop_up : Icons.arrow_drop_down, isOpen ? Icons.arrow_drop_up : Icons.arrow_drop_down,
color: Colors.white color: Colors.white
......
...@@ -103,7 +103,7 @@ class SlideTransition extends AnimatedWidget { ...@@ -103,7 +103,7 @@ class SlideTransition extends AnimatedWidget {
/// The [position] argument must not be null. /// The [position] argument must not be null.
const SlideTransition({ const SlideTransition({
Key key, Key key,
@required Animation<FractionalOffset> position, @required Animation<FractionalOffsetGeometry> position,
this.transformHitTests: true, this.transformHitTests: true,
this.child, this.child,
}) : super(key: key, listenable: position); }) : super(key: key, listenable: position);
...@@ -112,7 +112,7 @@ class SlideTransition extends AnimatedWidget { ...@@ -112,7 +112,7 @@ class SlideTransition extends AnimatedWidget {
/// ///
/// If the current value of the position animation is (dx, dy), the child will /// If the current value of the position animation is (dx, dy), the child will
/// be translated horizontally by width * dx and vertically by height * dy. /// be translated horizontally by width * dx and vertically by height * dy.
Animation<FractionalOffset> get position => listenable; Animation<FractionalOffsetGeometry> get position => listenable;
/// Whether hit testing should be affected by the slide animation. /// Whether hit testing should be affected by the slide animation.
/// ///
...@@ -244,11 +244,11 @@ class SizeTransition extends AnimatedWidget { ...@@ -244,11 +244,11 @@ class SizeTransition extends AnimatedWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
FractionalOffset alignment; FractionalOffsetDirectional alignment;
if (axis == Axis.vertical) if (axis == Axis.vertical)
alignment = new FractionalOffset(0.0, axisAlignment); alignment = new FractionalOffsetDirectional(0.0, axisAlignment);
else else
alignment = new FractionalOffset(axisAlignment, 0.0); alignment = new FractionalOffsetDirectional(axisAlignment, 0.0);
return new ClipRect( return new ClipRect(
child: new Align( child: new Align(
alignment: alignment, alignment: alignment,
......
...@@ -8,7 +8,14 @@ import '../rendering/mock_canvas.dart'; ...@@ -8,7 +8,14 @@ import '../rendering/mock_canvas.dart';
void main() { void main() {
testWidgets('Divider control test', (WidgetTester tester) async { testWidgets('Divider control test', (WidgetTester tester) async {
await tester.pumpWidget(const Center(child: const Divider())); await tester.pumpWidget(
const Directionality(
textDirection: TextDirection.ltr,
child: const Center(
child: const Divider(),
),
),
);
final RenderBox box = tester.firstRenderObject(find.byType(Divider)); final RenderBox box = tester.firstRenderObject(find.byType(Divider));
expect(box.size.height, 16.0); expect(box.size.height, 16.0);
expect(find.byType(Divider), paints..path(strokeWidth: 0.0)); expect(find.byType(Divider), paints..path(strokeWidth: 0.0));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment