Add a layoutDirection parameter to AndroidView (#20838)


diff --git a/packages/flutter/lib/src/services/platform_views.dart b/packages/flutter/lib/src/services/platform_views.dart
index 78726ae..89f47df 100644
--- a/packages/flutter/lib/src/services/platform_views.dart
+++ b/packages/flutter/lib/src/services/platform_views.dart
@@ -59,16 +59,21 @@
   ///
   /// The Android view will only be created after [AndroidViewController.setSize] is called for the
   /// first time.
+  ///
+  /// The `id, `viewType, and `layoutDirection` parameters must not be null.
   static AndroidViewController initAndroidView({
     @required int id,
     @required String viewType,
+    @required TextDirection layoutDirection,
     PlatformViewCreatedCallback onPlatformViewCreated,
   }) {
     assert(id != null);
     assert(viewType != null);
+    assert(layoutDirection != null);
     return new AndroidViewController._(
         id,
         viewType,
+        layoutDirection,
         onPlatformViewCreated
     );
   }
@@ -343,10 +348,13 @@
   AndroidViewController._(
     this.id,
     String viewType,
+    TextDirection layoutDirection,
     PlatformViewCreatedCallback onPlatformViewCreated,
   ) : assert(id != null),
       assert(viewType != null),
+      assert(layoutDirection != null),
       _viewType = viewType,
+      _layoutDirection = layoutDirection,
       _onPlatformViewCreated = onPlatformViewCreated,
       _state = _AndroidViewState.waitingForSize;
 
@@ -380,6 +388,12 @@
   /// Android's [MotionEvent.ACTION_POINTER_UP](https://developer.android.com/reference/android/view/MotionEvent#ACTION_POINTER_UP)
   static const int kActionPointerUp =  6;
 
+  /// Android's [View.LAYOUT_DIRECTION_LTR](https://developer.android.com/reference/android/view/View.html#LAYOUT_DIRECTION_LTR) value.
+  static const int kAndroidLayoutDirectionLtr = 0;
+
+  /// Android's [View.LAYOUT_DIRECTION_RTL](https://developer.android.com/reference/android/view/View.html#LAYOUT_DIRECTION_RTL) value.
+  static const int kAndroidLayoutDirectionRtl = 1;
+
   /// The unique identifier of the Android view controlled by this controller.
   final int id;
 
@@ -396,6 +410,8 @@
   /// disposed.
   int get textureId => _textureId;
 
+  TextDirection _layoutDirection;
+
   _AndroidViewState _state;
 
   /// Disposes the Android view.
@@ -430,6 +446,37 @@
     });
   }
 
+  /// Sets the layout direction for the Android view.
+  Future<void> setLayoutDirection(TextDirection layoutDirection) async {
+    if (_state == _AndroidViewState.disposed)
+      throw new FlutterError('trying to set a layout direction for a disposed Android View. View id: $id');
+
+    if (layoutDirection == _layoutDirection)
+      return;
+
+    assert(layoutDirection != null);
+    _layoutDirection = layoutDirection;
+
+    // If the view was not yet created we just update _layoutDirection and return, as the new
+    // direction will be used in _create.
+    if (_state == _AndroidViewState.waitingForSize)
+      return;
+
+    await SystemChannels.platform_views.invokeMethod('setDirection', <String, dynamic> {
+      'id': id,
+      'direction': _getAndroidDirection(layoutDirection),
+    });
+  }
+
+  static int _getAndroidDirection(TextDirection direction) {
+    switch (direction) {
+      case TextDirection.ltr:
+        return kAndroidLayoutDirectionLtr;
+      case TextDirection.rtl:
+        return kAndroidLayoutDirectionRtl;
+    }
+  }
+
   /// Sends an Android [MotionEvent](https://developer.android.com/reference/android/view/MotionEvent)
   /// to the view.
   ///
@@ -454,6 +501,7 @@
       'viewType': _viewType,
       'width': size.width,
       'height': size.height,
+      'direction': _getAndroidDirection(_layoutDirection),
     });
     if (_onPlatformViewCreated != null)
       _onPlatformViewCreated(id);
diff --git a/packages/flutter/lib/src/widgets/platform_view.dart b/packages/flutter/lib/src/widgets/platform_view.dart
index 7d8f467..9e5bf18 100644
--- a/packages/flutter/lib/src/widgets/platform_view.dart
+++ b/packages/flutter/lib/src/widgets/platform_view.dart
@@ -6,6 +6,8 @@
 import 'package:flutter/rendering.dart';
 import 'package:flutter/services.dart';
 
+import 'basic.dart';
+import 'debug.dart';
 import 'framework.dart';
 
 /// Embeds an Android view in the Widget hierarchy.
@@ -45,6 +47,7 @@
     @required this.viewType,
     this.onPlatformViewCreated,
     this.hitTestBehavior = PlatformViewHitTestBehavior.opaque,
+    this.layoutDirection,
   }) : assert(viewType != null),
        assert(hitTestBehavior != null),
        super(key: key);
@@ -66,6 +69,11 @@
   /// This defaults to [PlatformViewHitTestBehavior.opaque].
   final PlatformViewHitTestBehavior hitTestBehavior;
 
+  /// The text direction to use for the embedded view.
+  ///
+  /// If this is null, the ambient [Directionality] is used instead.
+  final TextDirection layoutDirection;
+
   @override
   State createState() => new _AndroidViewState();
 }
@@ -73,6 +81,8 @@
 class _AndroidViewState extends State<AndroidView> {
   int _id;
   AndroidViewController _controller;
+  TextDirection _layoutDirection;
+  bool _initialized = false;
 
   @override
   Widget build(BuildContext context) {
@@ -82,19 +92,53 @@
     );
   }
 
-  @override
-  void initState() {
-    super.initState();
+  void _initializeOnce() {
+    if (_initialized) {
+      return;
+    }
+    _initialized = true;
+    _layoutDirection = _findLayoutDirection();
     _createNewAndroidView();
   }
 
   @override
+  void didChangeDependencies() {
+    super.didChangeDependencies();
+    _initializeOnce();
+
+    final TextDirection newLayoutDirection = _findLayoutDirection();
+    final bool didChangeLayoutDirection = _layoutDirection != newLayoutDirection;
+    _layoutDirection = newLayoutDirection;
+
+    if (didChangeLayoutDirection) {
+      // The native view will update asynchronously, in the meantime we don't want
+      // to block the framework. (so this is intentionally not awaiting).
+      _controller.setLayoutDirection(_layoutDirection);
+    }
+  }
+
+  @override
   void didUpdateWidget(AndroidView oldWidget) {
     super.didUpdateWidget(oldWidget);
-    if (widget.viewType == oldWidget.viewType)
+
+    final TextDirection newLayoutDirection = _findLayoutDirection();
+    final bool didChangeLayoutDirection = _layoutDirection != newLayoutDirection;
+    _layoutDirection = newLayoutDirection;
+
+    if (widget.viewType != oldWidget.viewType) {
+      _controller.dispose();
+      _createNewAndroidView();
       return;
-    _controller.dispose();
-    _createNewAndroidView();
+    }
+
+    if (didChangeLayoutDirection) {
+      _controller.setLayoutDirection(_layoutDirection);
+    }
+  }
+
+  TextDirection _findLayoutDirection() {
+    assert(widget.layoutDirection != null || debugCheckHasDirectionality(context));
+    return widget.layoutDirection ?? Directionality.of(context);
   }
 
   @override
@@ -108,10 +152,10 @@
     _controller = PlatformViewsService.initAndroidView(
         id: _id,
         viewType: widget.viewType,
+        layoutDirection: _layoutDirection,
         onPlatformViewCreated: widget.onPlatformViewCreated
     );
   }
-
 }
 
 class _AndroidPlatformView extends LeafRenderObjectWidget {
diff --git a/packages/flutter/test/services/fake_platform_views.dart b/packages/flutter/test/services/fake_platform_views.dart
index 50d4bae..76f792c 100644
--- a/packages/flutter/test/services/fake_platform_views.dart
+++ b/packages/flutter/test/services/fake_platform_views.dart
@@ -47,6 +47,8 @@
         return _resize(call);
       case 'touch':
         return _touch(call);
+      case 'setDirection':
+        return _setDirection(call);
     }
     return new Future<Null>.sync(() => null);
   }
@@ -57,6 +59,7 @@
     final String viewType = args['viewType'];
     final double width = args['width'];
     final double height = args['height'];
+    final int layoutDirection = args['direction'];
 
     if (_views.containsKey(id))
       throw new PlatformException(
@@ -70,7 +73,7 @@
         message: 'Trying to create a platform view of unregistered type: $viewType',
       );
 
-    _views[id] = new FakePlatformView(id, viewType, new Size(width, height));
+    _views[id] = new FakePlatformView(id, viewType, new Size(width, height), layoutDirection);
     final int textureId = _textureCounter++;
     return new Future<int>.sync(() => textureId);
   }
@@ -130,15 +133,31 @@
     return new Future<Null>.sync(() => null);
   }
 
+  Future<dynamic> _setDirection(MethodCall call) async {
+    final Map<dynamic, dynamic> args = call.arguments;
+    final int id = args['id'];
+    final int layoutDirection = args['direction'];
+
+    if (!_views.containsKey(id))
+      throw new PlatformException(
+        code: 'error',
+        message: 'Trying to resize a platform view with unknown id: $id',
+      );
+
+    _views[id].layoutDirection = layoutDirection;
+
+    return new Future<Null>.sync(() => null);
+  }
 }
 
 class FakePlatformView {
 
-  FakePlatformView(this.id, this.type, this.size);
+  FakePlatformView(this.id, this.type, this.size, this.layoutDirection);
 
   final int id;
   final String type;
   Size size;
+  int layoutDirection;
 
   @override
   bool operator ==(dynamic other) {
@@ -151,11 +170,11 @@
   }
 
   @override
-  int get hashCode => hashValues(id, type, size);
+  int get hashCode => hashValues(id, type, size, layoutDirection);
 
   @override
   String toString() {
-    return 'FakePlatformView(id: $id, type: $type, size: $size)';
+    return 'FakePlatformView(id: $id, type: $type, size: $size, layoutDirection: $layoutDirection)';
   }
 }
 
diff --git a/packages/flutter/test/services/platform_views_test.dart b/packages/flutter/test/services/platform_views_test.dart
index 09e2b5a..d8866e5 100644
--- a/packages/flutter/test/services/platform_views_test.dart
+++ b/packages/flutter/test/services/platform_views_test.dart
@@ -19,57 +19,66 @@
 
     test('create Android view of unregistered type', () async {
       expect(
-          () => PlatformViewsService.initAndroidView(
-              id: 0, viewType: 'web').setSize(const Size(100.0, 100.0)),
-          throwsA(isInstanceOf<PlatformException>()));
+        () {
+          return PlatformViewsService.initAndroidView(
+            id: 0,
+            viewType: 'web',
+            layoutDirection: TextDirection.ltr,
+          ).setSize(const Size(100.0, 100.0));
+        },
+        throwsA(isInstanceOf<PlatformException>()),
+      );
     });
 
     test('create Android views', () async {
       viewsController.registerViewType('webview');
-      await PlatformViewsService.initAndroidView(
-          id: 0, viewType: 'webview').setSize(const Size(100.0, 100.0));
-      await PlatformViewsService.initAndroidView(
-          id: 1, viewType: 'webview').setSize(const Size(200.0, 300.0));
+      await PlatformViewsService.initAndroidView(id: 0, viewType: 'webview', layoutDirection: TextDirection.ltr)
+          .setSize(const Size(100.0, 100.0));
+      await PlatformViewsService.initAndroidView( id: 1, viewType: 'webview', layoutDirection: TextDirection.rtl)
+          .setSize(const Size(200.0, 300.0));
       expect(
           viewsController.views,
           unorderedEquals(<FakePlatformView>[
-            new FakePlatformView(0, 'webview', const Size(100.0, 100.0)),
-            new FakePlatformView(1, 'webview', const Size(200.0, 300.0)),
+            new FakePlatformView(0, 'webview', const Size(100.0, 100.0), AndroidViewController.kAndroidLayoutDirectionLtr),
+            new FakePlatformView(1, 'webview', const Size(200.0, 300.0), AndroidViewController.kAndroidLayoutDirectionRtl),
           ]));
     });
 
     test('reuse Android view id', () async {
       viewsController.registerViewType('webview');
       await PlatformViewsService.initAndroidView(
-          id: 0, viewType: 'webview').setSize(const Size(100.0, 100.0));
+        id: 0,
+        viewType: 'webview',
+        layoutDirection: TextDirection.ltr,
+      ).setSize(const Size(100.0, 100.0));
       expect(
           () => PlatformViewsService.initAndroidView(
-              id: 0, viewType: 'web').setSize(const Size(100.0, 100.0)),
+              id: 0, viewType: 'web', layoutDirection: TextDirection.ltr).setSize(const Size(100.0, 100.0)),
           throwsA(isInstanceOf<PlatformException>()));
     });
 
     test('dispose Android view', () async {
       viewsController.registerViewType('webview');
       await PlatformViewsService.initAndroidView(
-          id: 0, viewType: 'webview').setSize(const Size(100.0, 100.0));
+          id: 0, viewType: 'webview', layoutDirection: TextDirection.ltr).setSize(const Size(100.0, 100.0));
       final AndroidViewController viewController =
-          PlatformViewsService.initAndroidView(id: 1, viewType: 'webview');
+          PlatformViewsService.initAndroidView(id: 1, viewType: 'webview', layoutDirection: TextDirection.ltr);
       await viewController.setSize(const Size(200.0, 300.0));
 
       viewController.dispose();
       expect(
           viewsController.views,
           unorderedEquals(<FakePlatformView>[
-            new FakePlatformView(0, 'webview', const Size(100.0, 100.0)),
+            new FakePlatformView(0, 'webview', const Size(100.0, 100.0), AndroidViewController.kAndroidLayoutDirectionLtr),
           ]));
     });
 
     test('dispose inexisting Android view', () async {
       viewsController.registerViewType('webview');
       await PlatformViewsService.initAndroidView(
-          id: 0, viewType: 'webview').setSize(const Size(100.0, 100.0));
+          id: 0, viewType: 'webview', layoutDirection: TextDirection.ltr).setSize(const Size(100.0, 100.0));
       final AndroidViewController viewController =
-          PlatformViewsService.initAndroidView(id: 1, viewType: 'webview');
+          PlatformViewsService.initAndroidView(id: 1, viewType: 'webview', layoutDirection: TextDirection.ltr);
       await viewController.setSize(const Size(200.0, 300.0));
       await viewController.dispose();
       await viewController.dispose();
@@ -78,16 +87,16 @@
     test('resize Android view', () async {
       viewsController.registerViewType('webview');
       await PlatformViewsService.initAndroidView(
-          id: 0, viewType: 'webview').setSize(const Size(100.0, 100.0));
+          id: 0, viewType: 'webview', layoutDirection: TextDirection.ltr).setSize(const Size(100.0, 100.0));
       final AndroidViewController viewController =
-          PlatformViewsService.initAndroidView(id: 1, viewType: 'webview');
+          PlatformViewsService.initAndroidView(id: 1, viewType: 'webview', layoutDirection: TextDirection.ltr);
       await viewController.setSize(const Size(200.0, 300.0));
       await viewController.setSize(const Size(500.0, 500.0));
       expect(
           viewsController.views,
           unorderedEquals(<FakePlatformView>[
-            new FakePlatformView(0, 'webview', const Size(100.0, 100.0)),
-            new FakePlatformView(1, 'webview', const Size(500.0, 500.0)),
+            new FakePlatformView(0, 'webview', const Size(100.0, 100.0), AndroidViewController.kAndroidLayoutDirectionLtr),
+            new FakePlatformView(1, 'webview', const Size(500.0, 500.0), AndroidViewController.kAndroidLayoutDirectionLtr),
           ]));
     });
 
@@ -97,19 +106,45 @@
       final PlatformViewCreatedCallback callback = (int id) { createdViews.add(id); };
 
       final AndroidViewController controller1 = PlatformViewsService.initAndroidView(
-          id: 0, viewType: 'webview', onPlatformViewCreated:  callback);
+          id: 0, viewType: 'webview', layoutDirection: TextDirection.ltr, onPlatformViewCreated:  callback);
       expect(createdViews, isEmpty);
 
       await controller1.setSize(const Size(100.0, 100.0));
       expect(createdViews, orderedEquals(<int>[0]));
 
       final AndroidViewController controller2 = PlatformViewsService.initAndroidView(
-          id: 5, viewType: 'webview', onPlatformViewCreated:  callback);
+          id: 5, viewType: 'webview', layoutDirection: TextDirection.ltr, onPlatformViewCreated:  callback);
       expect(createdViews, orderedEquals(<int>[0]));
 
       await controller2.setSize(const Size(100.0, 200.0));
       expect(createdViews, orderedEquals(<int>[0, 5]));
 
     });
+
+    test('change Android view\'s directionality before creation', () async {
+      viewsController.registerViewType('webview');
+      final AndroidViewController viewController =
+      PlatformViewsService.initAndroidView(id: 0, viewType: 'webview', layoutDirection: TextDirection.rtl);
+      await viewController.setLayoutDirection(TextDirection.ltr);
+      await viewController.setSize(const Size(100.0, 100.0));
+      expect(
+          viewsController.views,
+          unorderedEquals(<FakePlatformView>[
+            new FakePlatformView(0, 'webview', const Size(100.0, 100.0), AndroidViewController.kAndroidLayoutDirectionLtr),
+          ]));
+    });
+
+    test('change Android view\'s directionality after creation', () async {
+      viewsController.registerViewType('webview');
+      final AndroidViewController viewController =
+      PlatformViewsService.initAndroidView(id: 0, viewType: 'webview', layoutDirection: TextDirection.ltr);
+      await viewController.setSize(const Size(100.0, 100.0));
+      await viewController.setLayoutDirection(TextDirection.rtl);
+      expect(
+          viewsController.views,
+          unorderedEquals(<FakePlatformView>[
+            new FakePlatformView(0, 'webview', const Size(100.0, 100.0), AndroidViewController.kAndroidLayoutDirectionRtl),
+          ]));
+    });
   });
 }
diff --git a/packages/flutter/test/widgets/platform_view_test.dart b/packages/flutter/test/widgets/platform_view_test.dart
index fa03c02..fb4f9e3 100644
--- a/packages/flutter/test/widgets/platform_view_test.dart
+++ b/packages/flutter/test/widgets/platform_view_test.dart
@@ -24,7 +24,7 @@
         child: SizedBox(
           width: 200.0,
           height: 100.0,
-          child: AndroidView(viewType: 'webview'),
+          child: AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr),
         ),
       ),
     );
@@ -32,7 +32,7 @@
     expect(
       viewsController.views,
       unorderedEquals(<FakePlatformView>[
-        new FakePlatformView(currentViewId + 1, 'webview', const Size(200.0, 100.0))
+        new FakePlatformView(currentViewId + 1, 'webview', const Size(200.0, 100.0), AndroidViewController.kAndroidLayoutDirectionLtr)
       ]),
     );
   });
@@ -46,7 +46,7 @@
         child: SizedBox(
           width: 200.0,
           height: 100.0,
-          child: AndroidView(viewType: 'webview'),
+          child: AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr),
         ),
       ),
     );
@@ -58,7 +58,7 @@
         child: SizedBox(
           width: 100.0,
           height: 50.0,
-          child: AndroidView(viewType: 'webview'),
+          child: AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr),
         ),
       ),
     );
@@ -70,7 +70,7 @@
     expect(
       viewsController.views,
       unorderedEquals(<FakePlatformView>[
-        new FakePlatformView(currentViewId + 1, 'webview', const Size(200.0, 100.0))
+        new FakePlatformView(currentViewId + 1, 'webview', const Size(200.0, 100.0), AndroidViewController.kAndroidLayoutDirectionLtr)
       ]),
     );
 
@@ -80,7 +80,7 @@
     expect(
       viewsController.views,
       unorderedEquals(<FakePlatformView>[
-        new FakePlatformView(currentViewId + 1, 'webview', const Size(100.0, 50.0))
+        new FakePlatformView(currentViewId + 1, 'webview', const Size(100.0, 50.0), AndroidViewController.kAndroidLayoutDirectionLtr)
       ]),
     );
   });
@@ -95,7 +95,7 @@
         child: SizedBox(
           width: 200.0,
           height: 100.0,
-          child: AndroidView(viewType: 'webview'),
+          child: AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr),
         ),
       ),
     );
@@ -105,7 +105,7 @@
         child: SizedBox(
           width: 200.0,
           height: 100.0,
-          child: AndroidView(viewType: 'maps'),
+          child: AndroidView(viewType: 'maps', layoutDirection: TextDirection.ltr),
         ),
       ),
     );
@@ -113,7 +113,7 @@
     expect(
       viewsController.views,
       unorderedEquals(<FakePlatformView>[
-        new FakePlatformView(currentViewId + 2, 'maps', const Size(200.0, 100.0))
+        new FakePlatformView(currentViewId + 2, 'maps', const Size(200.0, 100.0), AndroidViewController.kAndroidLayoutDirectionLtr)
       ]),
     );
   });
@@ -126,7 +126,7 @@
         child: SizedBox(
           width: 200.0,
           height: 100.0,
-          child: AndroidView(viewType: 'webview'),
+          child: AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr),
         ),
       ),
     );
@@ -156,7 +156,7 @@
         child: new SizedBox(
           width: 200.0,
           height: 100.0,
-          child: new AndroidView(viewType: 'webview', key: key),
+          child: new AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr, key: key),
         ),
       ),
     );
@@ -167,7 +167,7 @@
           child: new SizedBox(
             width: 200.0,
             height: 100.0,
-            child: new AndroidView(viewType: 'webview', key: key),
+            child: new AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr, key: key),
           ),
         ),
       ),
@@ -176,7 +176,7 @@
     expect(
       viewsController.views,
       unorderedEquals(<FakePlatformView>[
-        new FakePlatformView(currentViewId + 1, 'webview', const Size(200.0, 100.0))
+        new FakePlatformView(currentViewId + 1, 'webview', const Size(200.0, 100.0), AndroidViewController.kAndroidLayoutDirectionLtr)
       ]),
     );
   });
@@ -191,7 +191,7 @@
         child: SizedBox(
           width: 200.0,
           height: 100.0,
-          child: AndroidView(viewType: 'webview'),
+          child: AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr,),
         ),
       ),
     );
@@ -230,6 +230,7 @@
                 child: AndroidView(
                   viewType: 'webview',
                   hitTestBehavior: PlatformViewHitTestBehavior.transparent,
+                  layoutDirection: TextDirection.ltr,
                 ),
               ),
             ),
@@ -272,6 +273,7 @@
                 child: AndroidView(
                   viewType: 'webview',
                   hitTestBehavior: PlatformViewHitTestBehavior.translucent,
+                  layoutDirection: TextDirection.ltr,
                 ),
               ),
             ),
@@ -316,6 +318,7 @@
                 child: AndroidView(
                   viewType: 'webview',
                   hitTestBehavior: PlatformViewHitTestBehavior.opaque,
+                  layoutDirection: TextDirection.ltr,
                 ),
               ),
             ),
@@ -350,7 +353,7 @@
           child: const SizedBox(
             width: 200.0,
             height: 100.0,
-            child: AndroidView(viewType: 'webview'),
+            child: AndroidView(viewType: 'webview', layoutDirection: TextDirection.ltr),
           ),
         ),
       ),
@@ -367,4 +370,88 @@
       ]),
     );
   });
+
+  testWidgets('Android view directionality', (WidgetTester tester) async {
+    final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
+    final FakePlatformViewsController viewsController = new FakePlatformViewsController(TargetPlatform.android);
+    viewsController.registerViewType('maps');
+    await tester.pumpWidget(
+      const Center(
+        child: SizedBox(
+          width: 200.0,
+          height: 100.0,
+          child: AndroidView(viewType: 'maps', layoutDirection: TextDirection.rtl),
+        ),
+      ),
+    );
+
+    expect(
+      viewsController.views,
+      unorderedEquals(<FakePlatformView>[
+        new FakePlatformView(currentViewId + 1, 'maps', const Size(200.0, 100.0), AndroidViewController.kAndroidLayoutDirectionRtl)
+      ]),
+    );
+
+    await tester.pumpWidget(
+      const Center(
+        child: SizedBox(
+          width: 200.0,
+          height: 100.0,
+          child: AndroidView(viewType: 'maps', layoutDirection: TextDirection.ltr),
+        ),
+      ),
+    );
+
+    expect(
+      viewsController.views,
+      unorderedEquals(<FakePlatformView>[
+        new FakePlatformView(currentViewId + 1, 'maps', const Size(200.0, 100.0), AndroidViewController.kAndroidLayoutDirectionLtr)
+      ]),
+    );
+  });
+
+  testWidgets('Android view ambient directionality', (WidgetTester tester) async {
+    final int currentViewId = platformViewsRegistry.getNextPlatformViewId();
+    final FakePlatformViewsController viewsController = new FakePlatformViewsController(TargetPlatform.android);
+    viewsController.registerViewType('maps');
+    await tester.pumpWidget(
+      const Directionality(
+        textDirection: TextDirection.rtl,
+        child: Center(
+          child: SizedBox(
+            width: 200.0,
+            height: 100.0,
+            child: AndroidView(viewType: 'maps'),
+          ),
+        ),
+      ),
+    );
+
+    expect(
+      viewsController.views,
+      unorderedEquals(<FakePlatformView>[
+        new FakePlatformView(currentViewId + 1, 'maps', const Size(200.0, 100.0), AndroidViewController.kAndroidLayoutDirectionRtl)
+      ]),
+    );
+
+    await tester.pumpWidget(
+      const Directionality(
+        textDirection: TextDirection.ltr,
+        child: Center(
+          child: SizedBox(
+            width: 200.0,
+            height: 100.0,
+            child: AndroidView(viewType: 'maps'),
+          ),
+        ),
+      ),
+    );
+
+    expect(
+      viewsController.views,
+      unorderedEquals(<FakePlatformView>[
+        new FakePlatformView(currentViewId + 1, 'maps', const Size(200.0, 100.0), AndroidViewController.kAndroidLayoutDirectionLtr)
+      ]),
+    );
+  });
 }