Saltar al contenido

Flutter setState del widget secundario sin reconstruir el padre

Hacemos una revisión profunda cada reseñas en nuestro espacio con la meta de mostrarte siempre información con la mayor veracidad y actualizada.

Solución:

Para un rendimiento óptimo, puede crear su propia envoltura alrededor Scaffold eso consigue el body como parámetro. los body el widget no se reconstruirá cuando setState es llamado en HideFabOnScrollScaffoldState.

Este es un patrón común que también se puede encontrar en widgets principales como AnimationBuilder.

import 'package:flutter/material.dart';

main() => runApp(MaterialApp(home: MyHomePage()));

class MyHomePage extends StatefulWidget 
  @override
  State createState() => MyHomePageState();


class MyHomePageState extends State 
  ScrollController controller = ScrollController();

  @override
  Widget build(BuildContext context) 
    return HideFabOnScrollScaffold(
      body: ListView.builder(
        controller: controller,
        itemBuilder: (context, i) => ListTile(title: Text('item $i')),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () ,
        child: Icon(Icons.add),
      ),
      controller: controller,
    );
  


class HideFabOnScrollScaffold extends StatefulWidget 
  const HideFabOnScrollScaffold(
    Key key,
    this.body,
    this.floatingActionButton,
    this.controller,
  ) : super(key: key);

  final Widget body;
  final Widget floatingActionButton;
  final ScrollController controller;

  @override
  State createState() => HideFabOnScrollScaffoldState();


class HideFabOnScrollScaffoldState extends State 
  bool _fabVisible = true;

  @override
  void initState() 
    super.initState();
    widget.controller.addListener(_updateFabVisible);
  

  @override
  void dispose() 
    widget.controller.removeListener(_updateFabVisible);
    super.dispose();
  

  void _updateFabVisible() 
    final newFabVisible = (widget.controller.offset == 0.0);
    if (_fabVisible != newFabVisible) 
      setState(() 
        _fabVisible = newFabVisible;
      );
    
  

  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: widget.body,
      floatingActionButton: _fabVisible ? widget.floatingActionButton : null,
    );
  

Alternativamente, también podría crear un contenedor para FloatingActionButtonpero eso probablemente romperá la transición.

Creo que usar una transmisión es más simple y también bastante fácil.

Solo necesita publicar en la transmisión cuando llegue su evento y luego usar un generador de transmisión para responder a esos cambios.

Aquí estoy mostrando/ocultando un componente basado en el enfoque de un widget en la jerarquía de widgets.

He usado el paquete rxdart aquí, pero no creo que sea necesario. también es posible que desee hacerlo de todos modos porque la mayoría de las personas usarán el patrón BloC de todos modos.

import 'dart:async';
import 'package:rxdart/rxdart.dart';

class _PageState extends State 
  final _focusNode = FocusNode();

  final _focusStreamSubject = PublishSubject();
  Stream get _focusStream => _focusStreamSubject.stream;

  @override
  void initState() 
    super.initState();

    _focusNode.addListener(() 
      _focusStreamSubject.add(_focusNode.hasFocus);
    );
  

  @override
  void dispose() 
    _focusNode.dispose();
    super.dispose();
  


  @override
  Widget build(BuildContext context) 
    return Scaffold(
      body: Stack(
        children: [
          _buildVeryLargeComponent(),
          StreamBuilder(
            stream: _focusStream,
            builder: ((context, AsyncSnapshot snapshot) 
              if (snapshot.hasData && snapshot.data) 
                return Text("keyboard has focus")
              
              return Container();
            ),
          )
        ],
      ),
    );
  

Puede usar StatefulBuilder y usar su función setState para crear widgets debajo de él.

Ejemplo:

import 'package:flutter/material.dart';

class MyWidget extends StatefulWidget 
  @override
  _MyWidgetState createState() => _MyWidgetState();


class _MyWidgetState extends State 

  int count = 0;

  @override
  Widget build(BuildContext context) 
    return Column(
      children: [
        // put widget here that you do not want to update using _setState of StatefulBuilder
        Container(
          child: Text("I am static"),
        ),
        StatefulBuilder(builder: (_context, _setState) 
          // put widges here that you want to update using _setState
          return Column(
            children: [
              Container(
                child: Text("I am updated for $count times"),
              ),
              RaisedButton(
                  child: Text('Update'),
                  onPressed: () 
                    // Following only updates widgets under StatefulBuilder as we are using _setState
                    // that belong to StatefulBuilder
                    _setState(() 
                      count++;
                    );
                  )
            ],
          );
        ),
      ],
    );
  

Acuérdate de que tienes permiso de interpretar si descubriste tu incógnita en el momento preciso.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

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