Flutter: implementación de superposición

Las superposiciones permiten que los widgets secundarios independientes floten elementos visuales sobre otros widgets insertándolos en la pila de la superposición.

Este artículo analiza la implementación de Superposiciones en Flutter. Para implementar Overlay en Flutter, necesitamos conocer dos clases integradas de Flutter, la clase OverlayEntry y la clase OverlayState .

Entrada superpuesta: 

Hablando vagamente, OverlayEntry es un lugar en una superposición que puede contener un widget.

Constructor para la clase OverlayEntry:

OverlayEntry(
 {
  required WidgetBuilder builder,
  bool opaque = false,
  bool maintainState = false
 }
)

Propiedades de la clase OverlayEntry:

  • builder:    toma un generador de widgets.
  • opaco:   toma un valor booleano que decide si esta entrada ocluye toda la superposición. Si una entrada dice ser opaca, entonces, por eficiencia, la superposición omitirá las entradas de construcción debajo de esa entrada a menos que tengan el conjunto de estado de mantenimiento .
  • keepState:   toma un valor booleano y, si se establece en verdadero, construye con fuerza las entradas ocluidas debajo de una entrada opaca .

Métodos de la clase OverlayEntry:

  • eliminar:   elimina esta entrada de la superposición.

Estado superpuesto:

El estado actual de una superposición se usa para insertar OverlayEntries en la superposición.

Métodos de la clase OverlayState:

  • debugIsVisible:   Comprueba si el OverlayEntry dado es visible o no y devuelve un bool.
  • insert: inserta   la OverlayEntry dadaen la superposición.
  • insertAll:   toma una lista de OverlayEntries e inserta todas las entradas en la superposición. También puede especificar las propiedades anteriores y siguientes para indicar en qué orden se deben insertar las entradas.
  • reorganizar:    elimine todas las entradas enumeradas en la List of OverlayEntries dada , luego vuelva a insertarlas en la superposición en el orden indicado. 

Sé que no está muy interesado en leer teoría, así que pasemos a algunos ejemplos.

Ejemplo 1:

Dart

import 'package:flutter/material.dart';
  
class Example1 extends StatefulWidget {
  const Example1({Key key}) : super(key: key);
  
  @override
  _Example1State createState() => _Example1State();
}
  
class _Example1State extends State<Example1> {
  void _showOverlay(BuildContext context) async {
      
    // Declaring and Initializing OverlayState
    // and OverlayEntry objects
    OverlayState overlayState = Overlay.of(context);
    OverlayEntry overlayEntry;
    overlayEntry = OverlayEntry(builder: (context) {
        
      // You can return any widget you like here
      // to be displayed on the Overlay
      return Positioned(
        left: MediaQuery.of(context).size.width * 0.2,
        top: MediaQuery.of(context).size.height * 0.3,
        child: Container(
          width: MediaQuery.of(context).size.width * 0.8,
          child: Stack(
            children: [
              Image.asset(
                'images/commentCloud.png',
                colorBlendMode: BlendMode.multiply,
              ),
              Positioned(
                top: MediaQuery.of(context).size.height * 0.13,
                left: MediaQuery.of(context).size.width * 0.13,
                child: Row(
                  children: [
                    Material(
                      color: Colors.transparent,
                      child: Text(
                        'This is a button!',
                        style: TextStyle(
                            fontSize: MediaQuery.of(context).size.height * 0.03,
                            color: Colors.green),
                      ),
                    ),
                    SizedBox(
                      width: MediaQuery.of(context).size.width * 0.18,
                    ),
                    GestureDetector(
                      onTap: () {
                          
                        // When the icon is pressed the OverlayEntry
                        // is removed from Overlay
                        overlayEntry.remove();
                      },
                      child: Icon(Icons.close,
                          color: Colors.green,
                          size: MediaQuery.of(context).size.height * 0.025),
                    )
                  ],
                ),
              ),
            ],
          ),
        ),
      );
    });
  
    // Inserting the OverlayEntry into the Overlay
    overlayState.insert(overlayEntry);
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(
          'GeeksForGeeks Example 2',
          style: TextStyle(fontWeight: FontWeight.bold),
        ),
      ),
      body: SafeArea(
          child: Center(
              child: MaterialButton(
        color: Colors.green,
        minWidth: MediaQuery.of(context).size.width * 0.4,
        height: MediaQuery.of(context).size.height * 0.06,
        child: Text(
          'show Overlay',
          style: TextStyle(color: Colors.white),
        ),
        onPressed: () {
          // calling the _showOverlay method 
          // when Button is pressed
          _showOverlay(context);
        },
      ))),
    );
  }
}

Explicación:

En esta aplicación flutter, he llamado a una función _showOverlay en la devolución de llamada onPressed del MaterialButton . En la función _showOverlay , he declarado e inicializado los objetos OverlayState y OverlayEntry . En OverlayEntry , pasé los widgets para una nube de comentarios y tiene un texto y un ícono , envolví el ícono con un GestureDetector y en su devolución de llamada onTap , llamé a la función de eliminación para OverlayEntry ., que elimina esta entrada de la superposición. También puede hacer que una OverlayEntry se elimine automáticamente después de una cierta duración, el siguiente ejemplo lo aborda. Después de la inicialización de OverlayEntry , llamé al método de inserción para OverlayState y pasé el OverlayEntry actual , esto agrega la Entrada a la Superposición .

Ejemplo 2:

Dart

import 'package:flutter/material.dart';
  
class Example2 extends StatefulWidget {
  const Example2({Key key}) : super(key: key);
  
  @override
  _Example2State createState() => _Example2State();
}
  
class _Example2State extends State<Example2> {
  void _showOverlay(BuildContext context) async {
      
    // Declaring and Initializing OverlayState
    // and OverlayEntry objects
    OverlayState overlayState = Overlay.of(context);
    OverlayEntry overlayEntry;
    overlayEntry = OverlayEntry(builder: (context) {
        
      // You can return any widget you like
      // here to be displayed on the Overlay
      return Positioned(
        left: MediaQuery.of(context).size.width * 0.2,
        top: MediaQuery.of(context).size.height * 0.3,
        child: Container(
          width: MediaQuery.of(context).size.width * 0.8,
          child: Stack(
            children: [
              Image.asset(
                'images/commentCloud.png',
                colorBlendMode: BlendMode.multiply,
              ),
              Positioned(
                top: MediaQuery.of(context).size.height * 0.13,
                left: MediaQuery.of(context).size.width * 0.13,
                child: Material(
                  color: Colors.transparent,
                  child: Text(
                    'I will disappear in 3 seconds.',
                    style: TextStyle(
                        fontSize: MediaQuery.of(context).size.height * 0.025,
                        color: Colors.green),
                  ),
                ),
              ),
            ],
          ),
        ),
      );
    });
  
    // Inserting the OverlayEntry into the Overlay
    overlayState.insert(overlayEntry);
  
    // Awaiting for 3 seconds
    await Future.delayed(Duration(seconds: 3));
  
    // Removing the OverlayEntry from the Overlay
    overlayEntry.remove();
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(
          'GeeksForGeeks Example 2',
          style: TextStyle(fontWeight: FontWeight.bold),
        ),
      ),
      body: SafeArea(
          child: Center(
              child: MaterialButton(
        color: Colors.green,
        minWidth: MediaQuery.of(context).size.width * 0.4,
        height: MediaQuery.of(context).size.height * 0.06,
        child: Text(
          'show Overlay',
          style: TextStyle(color: Colors.white),
        ),
        onPressed: () {
            
          // calling the _showOverlay method
          // when Button is pressed
          _showOverlay(context);
        },
      ))),
    );
  }
}

Producción:

Explicación:

En este ejemplo, he llamado a una función _showOverlay en la devolución de llamada onPressed de MaterialButton . En la función _showOverlay , he declarado e inicializado los objetos OverlayState y OverlayEntry . En OverlayEntry , pasé los widgets para una nube de comentarios y muestra un texto . Después de la inicialización de OverlayEntry , llamé al método de inserción para OverlayState y pasé el OverlayEntry actual , esto agrega la Entrada a la Superposición. Después de eso, tengo https://github.com/curiousyuvi/overlay_implementation esperado en Future.delayed para hacer un retraso de 3 segundos y luego llamé al método de eliminación para eliminar el OverlayEntry actual del Overlay . Esto hace que la entrada aparezca durante 3 segundos y luego desaparezca.

Ejemplo 3:

Dart

import 'package:flutter/material.dart';
  
class Example3 extends StatefulWidget {
  const Example3({Key key}) : super(key: key);
  
  @override
  _Example3State createState() => _Example3State();
}
  
class _Example3State extends State<Example3> {
  void _showOverlay(BuildContext context) async {
      
    // Declaring and Initializing OverlayState and
    // OverlayEntry objects
    OverlayState overlayState = Overlay.of(context);
    OverlayEntry overlayEntry1;
    OverlayEntry overlayEntry2;
    OverlayEntry overlayEntry3;
    overlayEntry1 = OverlayEntry(builder: (context) {
        
      // You can return any widget you like here
      // to be displayed on the Overlay
      return Positioned(
        left: MediaQuery.of(context).size.width * 0.1,
        top: MediaQuery.of(context).size.height * 0.3,
        child: ClipRRect(
          borderRadius: BorderRadius.circular(20),
          child: Container(
            padding: EdgeInsets.all(MediaQuery.of(context).size.height * 0.02),
            width: MediaQuery.of(context).size.width * 0.8,
            height: MediaQuery.of(context).size.height * 0.1,
            color: Colors.pink.withOpacity(0.3),
            child: Material(
              color: Colors.transparent,
              child: Text('I will disappear in 3 seconds',
                  style: TextStyle(
                      fontSize: MediaQuery.of(context).size.height * 0.03,
                      fontWeight: FontWeight.bold,
                      color: Colors.white)),
            ),
          ),
        ),
      );
    });
    overlayEntry2 = OverlayEntry(builder: (context) {
        
      // You can return any widget you like here
      // to be displayed on the Overlay
      return Positioned(
        left: MediaQuery.of(context).size.width * 0.1,
        top: MediaQuery.of(context).size.height * 0.5,
        child: ClipRRect(
          borderRadius: BorderRadius.circular(20),
          child: Container(
            padding: EdgeInsets.all(MediaQuery.of(context).size.height * 0.02),
            width: MediaQuery.of(context).size.width * 0.8,
            height: MediaQuery.of(context).size.height * 0.1,
            color: Colors.blue.withOpacity(0.3),
            child: Material(
              color: Colors.transparent,
              child: Text('I will disappear in 5 seconds',
                  style: TextStyle(
                      fontSize: MediaQuery.of(context).size.height * 0.03,
                      fontWeight: FontWeight.bold,
                      color: Colors.white)),
            ),
          ),
        ),
      );
    });
    overlayEntry3 = OverlayEntry(builder: (context) {
        
      // You can return any widget you like 
      // here to be displayed on the Overlay
      return Positioned(
        left: MediaQuery.of(context).size.width * 0.1,
        top: MediaQuery.of(context).size.height * 0.7,
        child: ClipRRect(
          borderRadius: BorderRadius.circular(20),
          child: Container(
            padding: EdgeInsets.all(MediaQuery.of(context).size.height * 0.02),
            width: MediaQuery.of(context).size.width * 0.8,
            height: MediaQuery.of(context).size.height * 0.1,
            color: Colors.green.withOpacity(0.3),
            child: Material(
              color: Colors.transparent,
              child: Text('I will disappear in 7 seconds',
                  style: TextStyle(
                      fontSize: MediaQuery.of(context).size.height * 0.03,
                      fontWeight: FontWeight.bold,
                      color: Colors.white)),
            ),
          ),
        ),
      );
    });
  
    // Inserting the OverlayEntry into the Overlay
    overlayState.insertAll([overlayEntry1, overlayEntry2, overlayEntry3]);
  
    // Awaiting for 3 seconds
    await Future.delayed(Duration(seconds: 3));
  
    // Removing the first OverlayEntry from the Overlay
    overlayEntry1.remove();
  
    // Awaiting for 2 seconds more
    await Future.delayed(Duration(seconds: 2));
  
    // Removing the second OverlayEntry from the Overlay
    overlayEntry2.remove();
  
    // Awaiting for 2 seconds more
    await Future.delayed(Duration(seconds: 2));
  
    // Removing the third OverlayEntry from the Overlay
    overlayEntry3.remove();
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(
          'GeeksForGeeks Example 3',
          style: TextStyle(fontWeight: FontWeight.bold),
        ),
      ),
      body: SafeArea(
          child: Center(
              child: MaterialButton(
        color: Colors.green,
        minWidth: MediaQuery.of(context).size.width * 0.4,
        height: MediaQuery.of(context).size.height * 0.06,
        child: Text(
          'show Overlay',
          style: TextStyle(color: Colors.white),
        ),
        onPressed: () {
            
          //calling the _showOverlay method
          // when Button is pressed
          _showOverlay(context);
        },
      ))),
    );
  }
}

Producción:

Explicación:

En este ejemplo, he llamado a una función _showOverlay en la devolución de llamada onPressed de MaterialButton . En la función _showOverlay , he declarado e inicializado OverlayState y tres objetos OverlayEntry . En estas entradas de superposición , tengo contenedores de diferentes colores y todos muestran un texto . Después de la inicialización de OverlayEntries , llamé al método insertAll para OverlayState y lo pasé en la Lista de OverlayEntries , esto agrega todas las Entradas alsuperposición _ Después de eso, esperé en Future.delayed para hacer una demora de 3 segundos y luego llaméal método remove para eliminar la primera OverlayEntry de la superposición y luego, de manera similar, me retrasé dos segundos, luego llamé a remove para la segunda OverlayEntry y luego retrasé nuevamente para 2 segundos y llamado remove para la tercera y última OverlayEntry , esto hace que las OverlayEntries desaparezcan una tras otra.

Publicación traducida automáticamente

Artículo escrito por curiousyuvi y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *