第一次单击后如何禁用按钮?

时间:2019-03-21 03:50:10

标签: dart flutter

多次单击按钮,多次打开页面。如何解决这个问题?我还将gif文件上传到了我的应用程序中(双击图像)。

     Container(
                            padding: EdgeInsets.all(10.0),
                            child: ButtonTheme(
                              minWidth: 10.0,
                              height: 40.0,
                              child: RaisedButton(
                                child: Text(
                                  AppTranslations.of(context)
                                      .text("loginpage_button"),
                                  style: TextStyle(
                                      color: Colors.white, fontSize: 15.0),
                                ),
                                onPressed: () async{
                                  (isOffline)
                                    ? _showSnackBar()
                                      : checking2(usernameController, context, _url);
                                },
                                color: Colors.blue,
                                padding: EdgeInsets.all(20.0),
                              ),
                            ),
margin: EdgeInsets.only(top: 0.0),

我使用了此代码,它可以正常工作,但是用户输入的用户名错误,用户无法单击按钮的第二种类型。这是我的代码。

onPressed: () async {
 if (_firstClick) {
_firstClick = false;
(isOffline)
? _showSnackBar()
: checking2(usernameController, context, _url);
}

enter image description here

7 个答案:

答案 0 :(得分:1)

我为自己写了两节课,可能对其他人有帮助。它们将其他人给出的答案封装在该线程中,这样您就不会到处都是笨蛋和赋值语句。

将函数传递给类,然后使用类的“调用”方法代替函数。目前,该功能不支持需要参数的功能,但对于无效情况很有用。

typedef void CallOnceFunction();
class CallOnce {
  bool _inFunction = false;

  final CallOnceFunction function;

  CallOnce(CallOnceFunction function) :
    assert(function != null),
    function = function
  ;

  void invoke() {
    if (_inFunction)
      return;

    _inFunction = true;
    function();
    _inFunction = false;
  }
}

typedef Future<void> CallOnceFuture();
class CallFutureOnce {
  bool _inFunction = false;

  final CallOnceFuture future;

  CallFutureOnce(CallOnceFuture future) :
    assert(future != null),
    future = future
  ;

  Future<void> invoke() async {
    if (_inFunction)
      return;

    _inFunction = true;
    await this.future();
    _inFunction = false;
  }
}

更新:这是这两个类的实际示例

/*Example*/
import 'package:flutter/material.dart';

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

class MyWidgetState extends State<MyWidget> {

  CallOnce _callOnce;
  CallFutureOnce _callFutureOnce;

  void myFunction() {
    /*Custom Code*/
  }

  Future<void> myFutureFunction() async {
    /*Custom Code*/
    //await something()
  }

  @override
  void initState() {
    super.initState();

    this._callOnce = CallOnce(this.myFunction);
    this._callFutureOnce = CallFutureOnce(this.myFutureFunction);
  }

  @override
  Widget build(BuildContext context) {

    return Scaffold (
      body: Center (
        child: RaisedButton (
          child: Text('Try Me'),
          onPressed: this._callOnce.invoke,
        ),
      ),
      floatingActionButton: FloatingActionButton (
        child: Icon(Icons.save),
        onPressed: this._callFutureOnce.invoke,
      ),
    );
  }
}

答案 1 :(得分:1)

基于计算时差在我的应用程序中解决了这个问题。

首先,声明一个DateTime变量并按如下所示定义函数:-

DateTime loginClickTime;

bool isRedundentClick(DateTime currentTime){
if(loginClickTime==null){
  loginClickTime = currentTime;
  print("first click");
  return false;
}
print('diff is ${currentTime.difference(loginClickTime).inSeconds}');
if(currentTime.difference(loginClickTime).inSeconds<10){//set this difference time in seconds
  return true;
}

loginClickTime = currentTime;
return false;
}

在登录按钮中,按如下所示调用函数以检查冗余:-

RaisedButton(
        child:Text('Login'),
        onPressed: (){
          if(isRedundentClick(DateTime.now())){
            print('hold on, processing');
            return;
          }
          print('run process');
          },
      )

答案 2 :(得分:0)

您可以使用bool变量来保存RaisedButton的状态:

首先创建变量并为其设置初始值:

  var _firstPress = true ;

然后在_firstPress函数内添加onPressed

                  Container(
                    padding: EdgeInsets.all(10.0),
                    child: ButtonTheme(
                      minWidth: 10.0,
                      height: 40.0,
                      child: RaisedButton(
                        child: Text(
                          AppTranslations.of(context)
                              .text("loginpage_button"),
                          style: TextStyle(
                              color: Colors.white, fontSize: 15.0),
                        ),
                        onPressed: () async{
                        // This is what you should add in your code
                        if(_firstPress){
                          _firstPress = false ;
                          (isOffline) ? _showSnackBar() :checking2(usernameController, context, _url);
                          }
                        },
                        color: Colors.blue,
                        padding: EdgeInsets.all(20.0),
                      ),
                    ),

                    margin: EdgeInsets.only(top: 0.0),
                    )

这样,您的onPressed函数将只响应RaisedButton的第一次单击。

答案 3 :(得分:0)

在这里How do I disable a Button in Flutter?

回答了这个问题

所有您需要使用statefulWidget并创建一个变量来保存您的条件,并根据您的事件对其进行更改。您的按钮将根据变量的值启用或禁用。

假设变量的初始状态isDisable = false,这意味着-默认情况下您的按钮处于启用状态。在第一次单击更改后,您的状态变量的值为isDisable = true。

答案 4 :(得分:0)

您可以将其变成StatefulWidget,而不是直接使用RaisedButton。然后使用ChangeNotifier将其状态从启用更改为禁用并控制按钮按下功能,这还将帮助您在不同位置重用它。这是一个示例,您如何做到这一点

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final ValueNotifier<MyButtonState> _myButtonStateChangeNotifier =
  ValueNotifier(MyButtonState.enable);

  @override
  Widget build(BuildContext context) {

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: MyButton(
          buttonStateChangeNotifier: _myButtonStateChangeNotifier,
          onPressed: _onButtonPressed,
          text: "Click Me",
        ),
      ),
    );
  }

  _onButtonPressed() {
    print("Button Pressed");
    _myButtonStateChangeNotifier.value = MyButtonState.disable;
  }

}

enum MyButtonState {enable, disable}

class MyButton extends StatefulWidget {
  final VoidCallback onPressed;
  final String text;
  final TextStyle textStyle;
  final ValueNotifier<MyButtonState> buttonStateChangeNotifier;

  MyButton({
    @required this.onPressed,
    this.text = "",
    this.textStyle,
    this.buttonStateChangeNotifier,
  });

  @override
  _MyButtonState createState() => _MyButtonState();
}

class _MyButtonState extends State<MyButton> {
  MyButtonState _myButtonState = MyButtonState.enable;
  @override
  void initState() {
    super.initState();
    if (widget.buttonStateChangeNotifier != null) {
      widget.buttonStateChangeNotifier.addListener(_handleButtonStateChange);
      _myButtonState = widget.buttonStateChangeNotifier.value;
    }
  }

  @override
  Widget build(BuildContext context) {
    return RaisedButton(
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.all(Radius.circular(4)),
      ),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text(widget.text)
        ],
      ),
      onPressed: _myButtonState == MyButtonState.enable
          ? _handleOnPress
          : null,
    );
  }

  _handleButtonStateChange() {
    setState(() {
      _myButtonState = widget.buttonStateChangeNotifier.value;
    });
  }

  _handleOnPress() {
    if (_myButtonState == MyButtonState.enable) {
      widget.onPressed();
    }
  }
}

答案 5 :(得分:0)

感谢上面的@Mazin Ibrahim's建议,设置基本的bool切换标记即可正常工作。

此实现基于在回调级别处理启用/禁用逻辑,而与小部件布局细节无关。

bool _isButtonEnabled = true;

MessageSql _messageSql = new MessageSql(); // DB helper class

final TextEditingController eCtrl = new TextEditingController();

_onSendMessage(String message) {

  if (! _isButtonEnabled) {
    return;
  }

  _isButtonEnabled = false;

  _messageSql.insert(message).then((resultId) {
    //  only update all if save is successful
    eCtrl.clear();

    AppUi.dismissKeyboard();

    _isButtonEnabled = true;

    Future.delayed(const Duration(milliseconds: 400), () {
      setState(() {});
    })
    .catchError((error, stackTrace) {
      print("outer: $error");
    });
}

答案 6 :(得分:0)

创建一个bool变量,当按下按钮时它将为true(因此,初始值设置为false)。

bool _clicked = false; 

@override
Widget build(BuildContext context) {
  return Scaffold(
    body: RaisedButton(
      child: Text('Button'),
      onPressed: _clicked
          ? null
          : () {
              setState(() => _clicked = true); // set it to true now
            },
    ),
  );
}