Як відключити кнопку "Flutter"?


116

Я тільки починаю зависати від Flutter, але у мене виникають проблеми з розумінням, як встановити ввімкнений стан кнопки.

У документах написано встановити onPressedзначення "null", щоб відключити кнопку, і надати їй значення, щоб увімкнути її. Це добре, якщо кнопка продовжує перебувати у тому ж стані протягом життєвого циклу.

У мене складається враження, що мені потрібно створити спеціальний віджет Stateful, який дозволить мені якось оновити ввімкнений стан кнопки (або onPress callback).

Тож моє запитання - як би я це зробив? Це здається досить простою вимогою, але я не можу знайти нічого в документах, як це зробити.

Дякую.


Чи можете ви уточнити, що ви маєте на увазі під цим "Це добре, якщо кнопка продовжує перебувати у тому ж стані протягом життєвого циклу". ?
Сет Ладд

Відповіді:


127

Думаю, ви можете ввести кілька допоміжних функцій у buildвашу кнопку, а також віджет Stateful разом із деяким властивістю, яке потрібно відключити.

  • Використовуйте StatefulWidget / State та створіть змінну для утримання вашого стану (наприклад isButtonDisabled)
  • Встановіть це істинно спочатку (якщо саме цього ви хочете)
  • Під час візуалізації кнопки не встановлюйтеonPressed значення ні на одну, nullні на якусь функціюonPressed: () {}
  • Натомість умовно встановіть його за допомогою потрійної або хелперної функції (приклад нижче)
  • Перевірте isButtonDisabledчастину цього умовного і поверніть ту nullчи іншу функцію.
  • При натисканні кнопки (або коли ви хочете відключити кнопку) використовуйте setState(() => isButtonDisabled = true)для перегортання умовної змінної.
  • Flutter знову викличе build()метод у новому стані, і кнопка буде надана за допомогою nullобробника преси та буде відключена.

Ось ще декілька контекстів із використанням лічильника 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,
    );
  }
}

У цьому прикладі я використовую вбудований потрійний термін , щоб умовно встановити Textі onPressed, але, можливо, вам буде більш доцільним витягнути це у функцію (ви можете використовувати цей самий метод, щоб змінити текст кнопки):

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
Вам потрібно додати функцію стрілки жиру як аргумент, інакше функція _incrementCounter () буде викликана відразу при включенні кнопки. Таким чином, насправді чекатиме натискання кнопки: onPress повинен виглядати приблизно так:onPressed: _isButtonDisabled ? null : () => _incrementCounter
Віт Верес

2
@vitVeres, як правило, правда, але _counterButtonPress () повертає функцію, return () {}тому це навмисно. Я не хочу використовувати стрілку жиру тут, оскільки я хочу, щоб функція виконувала та повертала nullта відключала кнопку.
Ештон Томас

@AshtonThomas Так, у вилученому методі _counterButtonPress () це точно так, як ви пояснили, але я посилався на код з потрійним оператором, перш ніж ви запропонували вилучення. У вашому першому прикладі це призведе до виконання методу _incrementCounter (), коли кнопка повинна бути включена. Наступного разу спробую зазначити, що я маю на увазі точніше :)
Віт Верес

30
Що було не так у користуванні disabledмайном, команда Flutter? Це просто не інтуїтивно: - /
Curly

1
правильний шлях - за допомогою AbsorbPointer або IgnorePointer. Просто спосіб віджетів замість логіки з налаштуванням onPress to null.
ejdrian313

94

Згідно з документами:

"Якщо зворотний виклик onPress є нульовим, то кнопка буде відключена, і за замовчуванням буде нагадувати плоску кнопку у відключеному кольорі."

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

Отже, ви можете зробити щось подібне:

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

2
Судячи з документів, саме так воно має реалізовуватися. З прийнятими властивостями відповіді, як disabledElevation, disabledColorі DisabledTextColorне працюватиме за призначенням.
Joel Broström

Пф, дякую за це Стів, не планував переглядати весь код прийнятої відповіді. @ chris84948, подумайте про зміну цього на прийняту відповідь.
CularBytes


17

Налаштування

onPressed: null // disables click

і

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

1
У цьому рішенні значення onPressedзавжди є функцією, тому кнопка відображається як "натискання", хоча вона ігнорує подію натискання, якщо встановлено isEnabledвластивість. Щоб дійсно відключити кнопку, використовуйтеRaisedButton(onPressed: isEnabled ? _handleClick : null
Curly

15

Для конкретної та обмеженої кількості віджетів, загортаючи їх у віджет, IgnorePointer робить саме це: коли його ignoringвластивість встановлено на істинне, підвіджет (власне, все піддірево) не можна натискати.

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

В іншому випадку, якщо ви плануєте вимкнути ціле піддірево, загляньте в AbsorbPointer ().


9

Функція "Увімкнення та вимкнення" однакова для більшості віджетів.

Ex, кнопка, перемикач, прапорець тощо

Просто встановіть onPressedвластивість, як показано нижче

onPressed : nullповертає віджет "Інваліди"

onPressed : (){}або onPressed : _functionNameповертає віджет Enabled


6

Ви також можете використовувати AbsorbPointer, і ви можете використовувати його наступним чином:

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

Якщо ви хочете дізнатися більше про цей віджет, ви можете перевірити наступне посилання Flutter Docs


2
Ignore- / AbsorbPointer не вважає відключені стилі лише ПЕРЕМЕНЮ :-)
Pascal

5

На мій погляд, це найпростіший спосіб:

RaisedButton(
  child: Text("PRESS BUTTON"),
  onPressed: booleanCondition
    ? () => myTapCallback()
    : null
)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.