Comment désactiver un bouton dans Flutter?


116

Je commence tout juste à comprendre Flutter, mais j'ai du mal à comprendre comment définir l'état activé d'un bouton.

À partir de la documentation, il est indiqué de définir onPressedsur null pour désactiver un bouton et de lui donner une valeur pour l'activer. Cela convient si le bouton continue à être dans le même état pendant le cycle de vie.

J'ai l'impression que j'ai besoin de créer un widget Stateful personnalisé qui me permettra de mettre à jour l'état activé du bouton (ou le rappel onPressed) d'une manière ou d'une autre.

Ma question est donc de savoir comment procéder? Cela semble être une exigence assez simple, mais je ne trouve rien dans la documentation sur la façon de le faire.

Merci.


Pouvez-vous clarifier ce que vous entendez par "C'est très bien si le bouton continue à être dans le même état pendant le cycle de vie." ?
Seth Ladd

Réponses:


127

Je pense que vous voudrez peut-être introduire des fonctions d'aide à buildvotre bouton ainsi qu'un widget Stateful avec une propriété à désactiver.

  • Utilisez un StatefulWidget / State et créez une variable pour contenir votre condition (par exemple isButtonDisabled)
  • Réglez ceci sur true au départ (si c'est ce que vous désirez)
  • Lors du rendu du bouton, ne définissez pas directement laonPressed valeur sur l'une nullou l' autre fonctiononPressed: () {}
  • Au lieu de cela , définissez-le conditionnellement à l'aide d'une fonction ternaire ou d'assistance (exemple ci-dessous)
  • Vérifiez le isButtonDisableddans le cadre de cette condition et retournez l'une nullou l' autre fonction.
  • Lorsque vous appuyez sur le bouton (ou chaque fois que vous souhaitez désactiver le bouton), utilisez setState(() => isButtonDisabled = true)pour inverser la variable conditionnelle.
  • Flutter appellera à build()nouveau la méthode avec le nouvel état et le bouton sera rendu avec un nullgestionnaire de presse et sera désactivé.

Voici un peu plus de contexte en utilisant le projet de compteur Flutter.

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;
  bool _isButtonDisabled;

  @override
  void initState() {
    _isButtonDisabled = false;
  }

  void _incrementCounter() {
    setState(() {
      _isButtonDisabled = true;
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text("The App"),
      ),
      body: new Center(
        child: new Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            new Text(
              'You have pushed the button this many times:',
            ),
            new Text(
              '$_counter',
              style: Theme.of(context).textTheme.display1,
            ),
            _buildCounterButton(),
          ],
        ),
      ),
    );
  }

  Widget _buildCounterButton() {
    return new RaisedButton(
      child: new Text(
        _isButtonDisabled ? "Hold on..." : "Increment"
      ),
      onPressed: _isButtonDisabled ? null : _incrementCounter,
    );
  }
}

Dans cet exemple, j'utilise un ternaire en ligne pour définir conditionnellement le Textet onPressed, mais il peut être plus approprié pour vous de l'extraire dans une fonction (vous pouvez également utiliser cette même méthode pour modifier le texte du bouton):

Widget _buildCounterButton() {
    return new RaisedButton(
      child: new Text(
        _isButtonDisabled ? "Hold on..." : "Increment"
      ),
      onPressed: _counterButtonPress(),
    );
  }

  Function _counterButtonPress() {
    if (_isButtonDisabled) {
      return null;
    } else {
      return () {
        // do anything else you may want to here
        _incrementCounter();
      };
    }
  }

3
Vous devez ajouter la fonction de grosse flèche comme argument, sinon la fonction _incrementCounter () sera appelée immédiatement lorsque le bouton sera activé. De cette façon, il attendra que le bouton soit cliqué: Le onPressed devrait ressembler à ceci:onPressed: _isButtonDisabled ? null : () => _incrementCounter
Vit Veres

2
@vitVeres qui est généralement vrai mais le _counterButtonPress () renvoie une fonction return () {}donc c'est intentionnel. Je ne veux pas utiliser la grosse flèche ici car je veux que la fonction s'exécute et retourne nullet désactive le bouton.
Ashton Thomas

@AshtonThomas Oui, dans la méthode extraite _counterButtonPress (), c'est exactement comme vous l'avez expliqué, mais je faisais référence au code avec l'opérateur ternaire avant que vous ne suggériez l'extraction. Dans votre premier exemple, cela provoquera l'exécution de la méthode _incrementCounter () lorsque le bouton doit être activé. La prochaine fois, je vais essayer de préciser ce que je veux dire plus précisément :)
Vit Veres

30
Quel était le problème avec l'utilisation d'une disabledpropriété, l'équipe Flutter? Ce n'est tout simplement pas intuitif: - /
Curly

1
la manière correcte est avec AbsorbPointer ou IgnorePointer. Simplement de manière widget au lieu de logique avec la configuration de onPressed à null.
ejdrian313

95

Selon la documentation:

«Si le rappel onPressed est nul, alors le bouton sera désactivé et ressemblera par défaut à un bouton plat dans le disabledColor.»

https://docs.flutter.io/flutter/material/RaisedButton-class.html

Donc, vous pouvez faire quelque chose comme ceci:

    RaisedButton(
      onPressed: calculateWhetherDisabledReturnsBool() ? null : () => whatToDoOnPressed,
      child: Text('Button text')
    );

2
À en juger par la documentation, voici comment il doit être mis en œuvre. Avec les propriétés de réponse acceptées comme disabledElevation, disabledColoret DisabledTextColorne fonctionnera pas comme prévu.
Joel Broström

Pff merci pour cela Steve, ne prévoyait pas de parcourir tout le code de la réponse actuellement acceptée. @ chris84948, pensez à changer cela par la réponse acceptée.
CularBytes


17

Réglage

onPressed: null // disables click

et

onPressed: () => yourFunction() // enables click

1
Dans cette solution, la valeur de onPressedest toujours une fonction, de sorte que le bouton est rendu comme "cliquable" bien qu'il ignorera l'événement de clic si la isEnabledpropriété est définie. Pour vraiment désactiver le bouton, utilisezRaisedButton(onPressed: isEnabled ? _handleClick : null
Curly

15

Pour un nombre spécifique et limité de widgets, les envelopper dans un widget IgnorePointer fait exactement ceci: lorsque sa ignoringpropriété est définie sur true, le sous-widget (en fait, la sous-arborescence entière) n'est pas cliquable.

IgnorePointer(
    ignoring: true, // or false
    child: RaisedButton(
        onPressed: _logInWithFacebook,
        child: Text("Facebook sign-in"),
        ),
),

Sinon, si vous avez l'intention de désactiver un sous-arbre entier, regardez dans AbsorbPointer ().


9

Les fonctionnalités d'activation et de désactivation sont identiques pour la plupart des widgets.

Ex, bouton, interrupteur, case à cocher, etc.

Réglez simplement le onPressed propriété comme indiqué ci-dessous

onPressed : nullrenvoie le widget désactivé

onPressed : (){}ou onPressed : _functionNamerenvoie le widget activé


6

Vous pouvez également utiliser AbsorbPointer et vous pouvez l'utiliser de la manière suivante:

AbsorbPointer(
      absorbing: true, // by default is true
      child: RaisedButton(
        onPressed: (){
          print('pending to implement onPressed function');
        },
        child: Text("Button Click!!!"),
      ),
    ),

Si vous souhaitez en savoir plus sur ce widget, vous pouvez consulter le lien suivant Flutter Docs


2
Ignore- / AbsorbPointer ne considère pas les styles désactivés comme un RAPPEL :-)
Pascal

5

C'est le moyen le plus simple à mon avis:

RaisedButton(
  child: Text("PRESS BUTTON"),
  onPressed: booleanCondition
    ? () => myTapCallback()
    : null
)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.