Come si disabilita un pulsante in Flutter?


115

Sto appena iniziando a prendere confidenza con Flutter, ma non riesco a capire come impostare lo stato abilitato di un pulsante.

Dai documenti, dice di impostare onPressedsu null per disabilitare un pulsante e dargli un valore per abilitarlo. Questo va bene se il pulsante continua a essere nello stesso stato per il ciclo di vita.

Ho l'impressione di dover creare un widget Stateful personalizzato che mi consentirà di aggiornare in qualche modo lo stato abilitato del pulsante (o il callback onPressed).

Quindi la mia domanda è come potrei farlo? Questo sembra un requisito piuttosto semplice, ma non riesco a trovare nulla nei documenti su come farlo.

Grazie.


Puoi chiarire cosa intendi con "Questo va bene se il pulsante continua a essere nello stesso stato per il ciclo di vita". ?
Seth Ladd

Risposte:


127

Penso che potresti voler introdurre alcune funzioni di supporto al buildtuo pulsante e un widget Stateful insieme ad alcune proprietà da cui disattivare.

  • Usa un widget Stateful / State e crea una variabile per mantenere la tua condizione (ad es. isButtonDisabled)
  • Impostalo inizialmente su true (se è quello che desideri)
  • Durante il rendering del pulsante, non impostare direttamente ilonPressed valore su nessuna delle due nullfunzionionPressed: () {}
  • Invece , impostalo in modo condizionale usando una funzione ternaria o di aiuto (esempio sotto)
  • Controlla isButtonDisabledcome parte di questo condizionale e restituisci una nullo qualche funzione.
  • Quando si preme il pulsante (o ogni volta che si desidera disabilitare il pulsante) utilizzare setState(() => isButtonDisabled = true)per capovolgere la variabile condizionale.
  • Flutter chiamerà build()nuovamente il metodo con il nuovo stato e il pulsante verrà renderizzato con un nullpress handler e sarà disabilitato.

Ecco un po 'più di contesto usando il progetto Flutter counter.

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 questo esempio sto usando un ternario in linea per impostare condizionalmente Texte onPressed, ma potrebbe essere più appropriato estrarlo in una funzione (puoi usare lo stesso metodo anche per cambiare il testo del pulsante):

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
È necessario aggiungere la funzione freccia grossa come argomento, altrimenti la funzione _incrementCounter () verrà chiamata immediatamente quando il pulsante viene abilitato. In questo modo attenderà fino a quando non verrà cliccato il pulsante: onPressed dovrebbe apparire così:onPressed: _isButtonDisabled ? null : () => _incrementCounter
Vit Veres

2
@vitVeres che di solito è vero ma _counterButtonPress () restituisce una funzione, return () {}quindi è intenzionale. Non voglio usare la freccia grassa qui perché voglio che la funzione venga eseguita e restituisca nulle disabiliti il ​​pulsante.
Ashton Thomas

@AshtonThomas Sì, nel metodo estratto _counterButtonPress () è esattamente come hai spiegato, ma mi riferivo al codice con operatore ternario prima che tu suggerissi l'estrazione. Nel tuo primo esempio causerà l'esecuzione del metodo _incrementCounter () quando il pulsante dovrebbe essere abilitato. La prossima volta cercherò di sottolineare cosa intendo più precisamente :)
Vit Veres

30
Cosa c'era di sbagliato nell'usare una disabledproprietà, team Flutter? Questo non è intuitivo: - /
Ricci

1
il modo corretto è con AbsorbPointer o IgnorePointer. Semplicemente in modo widget invece di logica con l'impostazione di onPressed su null.
ejdrian313

93

Secondo i documenti:

"Se il callback onPressed è nullo, il pulsante sarà disabilitato e per impostazione predefinita assomiglierà a un pulsante piatto in disabledColor."

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

Quindi, potresti fare qualcosa del genere:

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

2
A giudicare dai documenti, è così che deve essere implementato. Con le proprietà di risposta accettate come disabledElevation, disabledColoreDisabledTextColor non funzionerà come previsto.
Joel Broström,

Pff grazie per questo Steve, non aveva intenzione di esaminare tutto il codice della risposta attualmente accettata. @ chris84948, valuta la possibilità di modificarlo nella risposta accettata.
CularBytes


17

Ambientazione

onPressed: null // disables click

e

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

1
In questa soluzione il valore di onPressedè sempre una funzione, quindi il pulsante viene reso come "cliccabile" sebbene ignorerà l'evento clic se la isEnabledproprietà è impostata. Per disabilitare davvero il pulsante, utilizzareRaisedButton(onPressed: isEnabled ? _handleClick : null
Ricci

15

Per un numero specifico e limitato di widget, avvolgerli in un widget IgnorePointer fa esattamente questo: quando la sua ignoringproprietà è impostata su true, il sotto-widget (in realtà, l'intero sottoalbero) non è cliccabile.

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

Altrimenti, se intendi disabilitare un'intera sottostruttura, guarda AbsorbPointer ().


9

La funzionalità Abilita e Disabilita è la stessa per la maggior parte dei widget.

Ex, pulsante, interruttore, casella di controllo ecc.

Basta impostare la onPressedproprietà come mostrato di seguito

onPressed : nullrestituisce widget disabilitato

onPressed : (){}o onPressed : _functionNamerestituisce il widget abilitato


6

Puoi anche usare AbsorbPointer e puoi usarlo nel modo seguente:

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

Se vuoi saperne di più su questo widget, puoi controllare il seguente link Flutter Docs


2
Ignore- / AbsorbPointer non considera gli stili disabilitati solo come un PROMEMORIA :-)
Pascal

4

Questo è il modo più semplice secondo me:

RaisedButton(
  child: Text("PRESS BUTTON"),
  onPressed: booleanCondition
    ? () => myTapCallback()
    : null
)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.