Saltar al contenido principal

Añadir una Flutter View a una aplicación Android

Aprende cómo realizar integraciones avanzadas a través de Flutter Views.

Integrando a través de una FlutterView requiere un poco más de trabajo que mediante FlutterActivity y FlutterFragment descritos anteriormente.

Fundamentalmente, el framework de Flutter en el lado de Dart requiere acceso a varios eventos y ciclos de vida a nivel de activity para funcionar. Dado que la FlutterView (que es una android.view.View) se puede añadir a cualquier activity que sea propiedad de la aplicación del desarrollador y dado que la FlutterView no tiene acceso a los eventos a nivel de activity, el desarrollador debe conectar manualmente esas uniones con el FlutterEngine.

La forma en que elijas enviar los eventos de las activities de tu aplicación a la FlutterView será específica de tu aplicación.

Un ejemplo

#
Video de ejemplo de añadir Flutter View

A diferencia de las guías para FlutterActivity y FlutterFragment, la integración de FlutterView se podría demostrar mejor con un proyecto de ejemplo.

Hay un proyecto de ejemplo en https://github.com/flutter/samples/tree/main/add_to_app/android_view para documentar una integración simple de FlutterView donde se utilizan FlutterViews para algunas de las celdas en una lista de tarjetas de RecyclerView, como se ve en el gif de arriba.

Enfoque general

#

La esencia general de la integración a nivel de FlutterView es que debes recrear las diversas interacciones entre tu Activity, la FlutterView y el FlutterEngine presentes en FlutterActivityAndFragmentDelegate en el código de tu propia aplicación. Las conexiones realizadas en el FlutterActivityAndFragmentDelegate se hacen automáticamente al usar una FlutterActivity o un FlutterFragment, pero dado que la FlutterView en este caso se está añadiendo a una Activity o Fragment en tu aplicación, debes recrear las conexiones manualmente. De lo contrario, la FlutterView no renderizará nada o presentará otras fallas de funcionalidad.

Una clase de ejemplo FlutterViewEngine muestra una posible implementación de este tipo de conexión específica de la aplicación entre una Activity, una FlutterView y un FlutterEngine.

APIs a implementar

#

La implementación mínima absoluta necesaria para que Flutter dibuje algo es:

También se deben llamar a los métodos inversos detachFromFlutterEngine y otros métodos de ciclo de vida en la clase LifecycleChannel para no filtrar recursos cuando la FlutterView o la Activity ya no estén visibles.

Además, consulta el resto de la implementación en la clase de demostración FlutterViewEngine o en el FlutterActivityAndFragmentDelegate para asegurar el correcto funcionamiento de otras características como el portapapeles, superposiciones de la UI del sistema, plugins, etc.

Vistas ajustadas al contenido

#

Por lo general, una FlutterView necesita dimensiones fijas, ya sea a través de sus propias dimensiones o al coincidir con las dimensiones del elemento padre. Esto se puede ver en el proyecto de ejemplo. Sin embargo, ahora es posible permitir que la FlutterView se ajuste al tamaño de su contenido. Al usar content_wrap tanto para el alto como para el ancho, una FlutterView puede ajustar su tamaño, como se muestra en el proyecto de ejemplo de vistas con tamaño de contenido.

  • Para habilitar la vista ajustada al contenido cuando implementes tu aplicación, añade la siguiente configuración en el archivo AndroidManifest.xml de tu proyecto bajo la etiqueta <application>:
xml
<meta-data
  android:name="io.flutter.embedding.android.EnableContentSizing"
  android:value="true" />

Restricciones

#

Dado que las vistas de Flutter ajustadas al contenido requieren que tu aplicación Flutter pueda cambiar su tamaño, algunos widgets no son compatibles.

  • Un widget con tamaño no delimitado (unbounded size), como un ListView.
  • Un widget que delega el tamaño en su elemento hijo, como LayoutBuilder.

En la práctica, esto significa que bastantes widgets comunes no son compatibles, tales como ScaffoldBuilder, CupertinoTimerPicker, o cualquier widget que dependa internamente de un LayoutBuilder. En caso de duda, puedes usar un UnconstrainedBox para probar la usabilidad de un widget para una vista ajustada al contenido, como se muestra en el siguiente ejemplo:

dart
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context)
  => MaterialApp(home: MyPage());
}

class MyPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: UnconstrainedBox(
          // TODO: Edit this line to check if a widget
          // can cause problems with content-sized views.
          child: Text('This works!'),
          // child: Column(children: [Column(children: [Expanded(child: Text('This blows up!'))])]),
          // child: ListView(children: [Text('This blows up!')]),
        )
    );
  }
}