92 votes

Comment mettre à jour l'état d'un ModalBottomSheet dans Flutter?

Ce code est très simple: affiche une feuille de fond modale et lorsque l'utilisateur clique sur le bouton, il augmente la hauteur de la feuille de 10.

Mais rien ne se passe. En fait, il ne met à jour sa taille que si l'utilisateur "glisse" la feuille du bas avec son doigt (je crois que le balayage provoque un setState interne sur la feuille).

Ma question est: comment appeler l'état de mise à jour d'un ModalBottomSheet?

 showModalBottomSheet(
    context: context,
    builder: (context) {
      return Container(
        height: heightOfModalBottomSheet,
        child: RaisedButton(

            onPressed: () {
              setState(() {
                heightOfModalBottomSheet += 10;
              });

            }),
      );
    });

351voto

mmahgoub Points 2195

Vous pouvez utiliser StatefulBuilder de Flutter pour envelopper votre ModalBottomSheet comme suit:

 showModalBottomSheet(
    context: context,
    builder: (context) {
      return StatefulBuilder(
          builder: (BuildContext context, StateSetter setState /*You can rename this!*/) {
        return Container(
          height: heightOfModalBottomSheet,
          child: RaisedButton(onPressed: () {
            setState(() {
              heightOfModalBottomSheet += 10;
            });
          }),
        );
      });
});

Veuillez noter que le nouveau setState remplacera votre widget principal setState mais vous pouvez simplement le renommer pour pouvoir définir l'état de votre widget parent et celui du modal.

 //This sets modal state
setModalState(() {
    heightOfModalBottomSheet += 10;
});
//This sets parent widget state
setState(() {
     heightOfModalBottomSheet += 10;
});

34voto

Lebohang Mbele Points 1006

Vous pouvez peut-être utiliser le showBottomSheet du ScaffoldState . en savoir plus ici sur ce showBottomSheet.

Cela affichera le bottomSheet et renverra un contrôleur PersistentBottomSheetController . avec ce contrôleur, vous pouvez appeler controller.SetState((){}) qui restituera le bottomSheet.

Voici un exemple

 PersistentBottomSheetController _controller; // <------ Instance variable
final _scaffoldKey = GlobalKey<ScaffoldState>(); // <---- Another instance variable
.
.
.
void _incrementBottomSheet(){
    _controller.setState(
        (){
            heightOfModalBottomSheet += 10;
        }
    )
}
.
void _createBottomSheet() async{
  _controller = await _scaffoldKey.currentState.showBottomSheet(
        context: context,
        builder: (context) {
           return Container(
               height: heightOfModalBottomSheet,
               child: RaisedButton(
               onPressed: () {
                  _incrementBottomSheet()
              }),
         );
      });
}

20voto

CopsOnRoad Points 4705

Capture d'écran:

entrez la description de l'image ici


Créez une classe:

 class MyBottomSheet extends StatefulWidget {
  @override
  _MyBottomSheetState createState() => _MyBottomSheetState();
}

class _MyBottomSheetState extends State<MyBottomSheet> {
  bool _flag = false;

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        FlutterLogo(
          size: 300,
          style: FlutterLogoStyle.stacked,
          textColor: _flag ? Colors.black : Colors.red,
        ),
        RaisedButton(
          onPressed: () => setState(() => _flag = !_flag),
          child: Text('Change Color'),
        )
      ],
    );
  }
}

Usage:

 showModalBottomSheet(
  context: context,
  builder: (_) => MyBottomSheet(),
);

11voto

Veuillez vous référer au code de travail ci-dessous. J'ai créé un nouveau widget avec état ( ModalBottomSheet ) pour le showModalBottomSheet . En appuyant sur un bouton, nous reconstruisons uniquement le ModalBottomSheet qui est beaucoup plus propre maintenant. Nous pouvons utiliser AnimationController si besoin d'animation pour changer la hauteur.

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

class ModalBottomSheet extends StatefulWidget {
  _ModalBottomSheetState createState() => _ModalBottomSheetState();
}

class _ModalBottomSheetState extends State<ModalBottomSheet>
    with SingleTickerProviderStateMixin {
  var heightOfModalBottomSheet = 100.0;

  Widget build(BuildContext context) {
    return Container(
      height: heightOfModalBottomSheet,
      child: RaisedButton(
          child: Text("Press"),
          onPressed: () {
            heightOfModalBottomSheet += 100;
            setState(() {});
          }),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new _MyHomePageState();
  }
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    Future(() => showModalBottomSheet(
        context: context,
        builder: (context) {
          return ModalBottomSheet();
        }));
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("Modal example"),
      ),
    );
  }
}

void main() {
  runApp(new MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(title: 'Flutter Demo', home: new MyHomePage());
  }
}

7voto

Rashid Iqbal Points 8

créer un StatefulWidget séparé pour le showModalBottomSheet (), comme

  showModalBottomSheet(
    context: context,
    builder: (ctx) {
      return MapBottomSheet();
    });

Statefulwidget de la feuille inférieure

 class MapBottomSheet extends StatefulWidget {
  @override
  _MapBottomSheetState createState() => _MapBottomSheetState();
}

class _MapBottomSheetState extends State<MapBottomSheet> {
  List<String> places = [];

  void _setPlaces(String place) {
    setState(() {
      places.add(place);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.black12,
      child: Column(
        children: [
          AppTextField(
            hint: "Search",
            onEditingComplete: () {},
            onChanged: (String text) {},
            onSubmitted: (String text) async {
              // Await the http get response, then decode the json-formatted response.
              var response = await http.get(Uri.parse(
                  'https://api.mapbox.com/geocoding/v5/mapbox.places/$text.json?access_token=pk.eyJ1IjoidjNyc2lvbjkiLCJhIjoiY2ttNnZldmk1MHM2ODJxanh1ZHZqa2I3ZCJ9.e8pZsg87rHx9FSM0pDDtlA&country=PK&fuzzyMatch=false&place=park'));
              if (response.statusCode == 200) {
                Map<String, dynamic> data = jsonDecode(response.body);
                print(data.toString());

                List<dynamic> features = data['features'];

                features.forEach((dynamic feature) {
                  setState(() {
                    _setPlaces(feature['place_name']);
                  });
                });
              } else {
                print('Request failed with status: ${response.statusCode}.');
              }
            },
          ),
          Expanded(
            child: Container(
              height: 250.0,
              width: double.infinity,
              child: ListView.builder(
                  itemCount: places.length,
                  itemBuilder: (ctx, idx) {
                    return Container(
                      child: Text(places[idx]),
                    );
                  }),
            ),
          ),
        ],
      ),
    );
    
  }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X