Wie deaktiviere ich einen Button in Flutter?

112

Ich fange gerade an, Flutter in den Griff zu bekommen, aber ich habe Probleme herauszufinden, wie ich den aktivierten Status einer Schaltfläche einstellen kann.

In den Dokumenten heißt es, onPressedauf null zu setzen, um eine Schaltfläche zu deaktivieren, und ihr einen Wert zu geben, um sie zu aktivieren. Dies ist in Ordnung, wenn sich die Schaltfläche während des gesamten Lebenszyklus im selben Zustand befindet.

Ich habe den Eindruck, dass ich ein benutzerdefiniertes Stateful-Widget erstellen muss, mit dem ich den Aktivierungsstatus der Schaltfläche (oder den onPressed-Rückruf) irgendwie aktualisieren kann.

Meine Frage ist also, wie würde ich das machen? Dies scheint eine ziemlich einfache Anforderung zu sein, aber ich kann in den Dokumenten nichts dazu finden.

Vielen Dank.

chris84948
quelle
Können Sie klarstellen, was Sie unter "Dies ist in Ordnung, wenn sich die Schaltfläche für den gesamten Lebenszyklus im selben Zustand befindet?". ?
Seth Ladd

Antworten:

124

Ich denke, Sie möchten vielleicht einige Hilfsfunktionen für buildIhre Schaltfläche sowie ein Stateful-Widget zusammen mit einer Eigenschaft zum Abschalten einführen .

  • Verwenden Sie einen StatefulWidget / Staat und erstellen Sie eine Variable Ihren Zustand zu halten (zB isButtonDisabled)
  • Setzen Sie dies zunächst auf true (wenn Sie dies wünschen).
  • Stellen Sie beim Rendern der Schaltfläche denonPressed Wert nicht direkt auf eine nulloder mehrere Funktionen einonPressed: () {}
  • Stellen Sie es stattdessen bedingt mit einer ternären oder einer Hilfsfunktion ein (Beispiel unten).
  • Überprüfen Sie dies isButtonDisabledals Teil dieser Bedingung und geben Sie eine nulloder mehrere Funktionen zurück.
  • Wenn die Taste gedrückt wird (oder wenn Sie die Taste deaktivieren möchten), verwenden Sie setState(() => isButtonDisabled = true)diese Option, um die bedingte Variable umzudrehen.
  • Flutter ruft die build()Methode mit dem neuen Status erneut auf und die Schaltfläche wird mit einem nullDruckhandler gerendert und deaktiviert.

Hier ist etwas mehr Kontext mit dem Flutter Counter-Projekt.

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,
    );
  }
}

In diesem Beispiel verwende ich ein Inline-Ternär, um das Textund bedingt festzulegen onPressed, aber es ist möglicherweise besser für Sie, dies in eine Funktion zu extrahieren (Sie können dieselbe Methode verwenden, um auch den Text der Schaltfläche zu ändern):

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();
      };
    }
  }
Ashton Thomas
quelle
3
Sie müssen die Fettpfeilfunktion als Argument hinzufügen, andernfalls wird die Funktion _incrementCounter () sofort aufgerufen, wenn die Schaltfläche aktiviert wird. Auf diese Weise wird es tatsächlich warten, bis die Schaltfläche angeklickt wird: Die onPressed sollte so aussehen:onPressed: _isButtonDisabled ? null : () => _incrementCounter
Vit Veres
2
@vitVeres das ist normalerweise wahr, aber _counterButtonPress () gibt eine Funktion zurück, return () {}also ist dies beabsichtigt. Ich möchte den fetten Pfeil hier nicht verwenden, da die Funktion nulldie Schaltfläche ausführen und zurückgeben und deaktivieren soll.
Ashton Thomas
@AshtonThomas Ja, in der extrahierten Methode _counterButtonPress () ist es genau so, wie Sie es erklärt haben, aber ich habe auf den Code mit ternärem Operator verwiesen, bevor Sie die Extraktion vorgeschlagen haben. In Ihrem ersten Beispiel wird die Methode _incrementCounter () ausgeführt, wenn die Schaltfläche aktiviert werden soll. Das nächste Mal werde ich versuchen, genauer darauf hinzuweisen, was ich meine :)
Vit Veres
29
Was war falsch an der Nutzung einer disabledImmobilie, Flutter-Team? Dies ist einfach nicht intuitiv: - /
Curly
1
Der richtige Weg ist mit AbsorbPointer oder IgnorePointer. Einfach Widget-Weg statt Logik beim Einrichten von onPressed auf null.
ejdrian313
92

Laut den Dokumenten:

"Wenn der onPressed-Rückruf null ist, wird die Schaltfläche deaktiviert und ähnelt standardmäßig einer flachen Schaltfläche in der deaktivierten Farbe."

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

Sie könnten also so etwas tun:

    RaisedButton(
      onPressed: calculateWhetherDisabledReturnsBool() ? null : () => whatToDoOnPressed,
      child: Text('Button text')
    );
Steve Alexander
quelle
2
Nach den Dokumenten zu urteilen, ist dies die Implementierung. Mit den akzeptierten Antwort Eigenschaften wie disabledElevation, disabledColorund DisabledTextColorwird nicht funktionieren wie vorgesehen.
Joel Broström
Pff, danke für diesen Steve, hatte nicht vor, den gesamten Code der aktuell akzeptierten Antwort durchzugehen. @ chris84948, erwägen Sie, dies in die akzeptierte Antwort zu ändern.
CularBytes
42

Die einfache Antwort lautet: onPressed : nullDeaktiviert.

BINAY THAPA MAGAR
quelle
18

Rahmen

onPressed: null // disables click

und

onPressed: () => yourFunction() // enables click
CopsOnRoad
quelle
1
In dieser Lösung ist der Wert von onPressedimmer eine Funktion, sodass die Schaltfläche als "anklickbar" gerendert wird, obwohl das Klickereignis ignoriert wird, wenn die isEnabledEigenschaft festgelegt ist. Um die Schaltfläche wirklich zu deaktivieren, verwenden SieRaisedButton(onPressed: isEnabled ? _handleClick : null
Curly
15

Für eine bestimmte und begrenzte Anzahl von Widgets führt das Umschließen in ein Widget IgnorePointer genau dies aus: Wenn seine ignoringEigenschaft auf true gesetzt ist, kann das Unter-Widget (eigentlich der gesamte Teilbaum) nicht angeklickt werden.

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

Wenn Sie andernfalls einen gesamten Teilbaum deaktivieren möchten, schauen Sie in AbsorbPointer () nach.

edmond
quelle
9

Die Funktionen zum Aktivieren und Deaktivieren sind für die meisten Widgets gleich.

Ex, Taste, Schalter, Kontrollkästchen usw.

Stellen Sie einfach die onPressedEigenschaft wie unten gezeigt ein

onPressed : nullGibt das deaktivierte Widget zurück

onPressed : (){}oder onPressed : _functionNamegibt das aktivierte Widget zurück

Vicky Salunkhe
quelle
6

Sie können den AbsorbPointer auch auf folgende Weise verwenden:

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

Wenn Sie mehr über dieses Widget erfahren möchten, können Sie den folgenden Link Flutter Docs überprüfen

Juanes30
quelle
2
Ignore- / AbsorbPointer betrachtet die deaktivierten Stile nicht nur als ERINNERUNG :-)
Pascal
4

Dies ist meiner Meinung nach der einfachste Weg:

RaisedButton(
  child: Text("PRESS BUTTON"),
  onPressed: booleanCondition
    ? () => myTapCallback()
    : null
)
MatPag
quelle