как мне показывать / скрывать кнопки на основе определенных условий в flutter?

#firebase #dart #flutter

# #firebase #dart #flutter

Вопрос:

Я пытаюсь выяснить, как скрыть мои кнопки входа / регистрации, если пользователь вошел в систему или вышел.

Я посмотрел на ВИДИМОСТЬ и УШЕЛ, любой из них будет работать. Однако я не могу найти никаких руководств, соответствующих тому, что я пытаюсь выполнить.

Вот несколько фрагментов кода для того, что я пытаюсь выполнить:

Редактировать из исходного сообщения:

При аутентификации.dart (только функции):

 loginUser(context) async {
  formkey.currentState.save();
  if (formkey.currentState.validate()) {
    await _auth
        .signInWithEmailAndPassword(email: _email, password: _password)
        .catchError((e) {
          home.changeState(null);
      Fluttertoast.showToast(
          msg: "Invalid email and/or password. Please try again",
          toastLength: Toast.LENGTH_LONG,
          gravity: ToastGravity.TOP,
          timeInSecForIos: 5,
          backgroundColor: Colors.red,
          textColor: Colors.white,
          fontSize: 16.0
      );
    }).then((newUser) {
      var now = new DateTime.now();
      Firestore.instance
          .collection('users')
          .document(newUser.uid)
          .collection('userInfo')
          .document('userInfo')
          .setData({
        'Last login': now,
      }).catchError((e) {
        Fluttertoast.showToast(
            msg: "Update user failed: $e",
            toastLength: Toast.LENGTH_LONG,
            gravity: ToastGravity.TOP,
            timeInSecForIos: 1,
            backgroundColor: Colors.red,
            textColor: Colors.white,
            fontSize: 16.0
        );
      });
      welcomeUser();
      Navigator.of(context).pop();
    });
  }
  final user = await getSignedInUser();
  home.changeState(user);
}

getSignedInUser() async {

  mCurrentUser = await FirebaseAuth.instance.currentUser();
  if(mCurrentUser == null || mCurrentUser.isAnonymous){
    return null;
  }
  else{
    return mCurrentUser;
  }
}

signOutUser () async{
  await _auth.signOut();
  final user = await getSignedInUser();
  home.changeState(user);
}



HomeScreen home; //create instance of homescreen class, so I could call my function
 

На экране входа в систему (часть для создания кнопки для входа в систему):

 Expanded(
    child: OutlineButton(
       child: Text("Login "),
       onPressed: () =>
               loginUser(context)),
               flex: 1,
         ),
 

Класс рабочего стола (опущенные нерелевантные функции):

 class HomeScreen extends State<MyApp> {
  FirebaseUser currentUser; //not sure what to initialize this to upon loading app because user might still be signed in.
  final formkey = GlobalKey<FormState>();
  @override
  Widget build(BuildContext context){
    return MaterialApp(
      home: Scaffold(
          resizeToAvoidBottomPadding: false,
          appBar: AppBar(title: Text("HikeLocator"), backgroundColor: Colors.green[700],
          ),
          body: Container(
              margin: EdgeInsets.all(20.0),
              child: Form(
                key: formkey,
                child:
                Column(
                  children: <Widget>[
                    distanceFromUser(),
                    lengthOfTrail(),
                    numOfResults(),
                    Container(
                      margin: EdgeInsets.only(top: 25.0),
                    ),
                    submitButton(),
                   // loginButton(),
                    //signupButton(),
                    //logoutButton(),
                    //profile(),
                  ]   (currentUser == null ? [
                    loginButton(),
                    signupButton(),
                  ] : [ // logged in? show the following widgets
                  logoutButton(),
                  profile(),
                ]),
                ),
              )
          ),
      ),
    );
  }


  Widget loginButton() {
    return RaisedButton(
      color: Color.fromRGBO(58, 66, 86, 1.0),
      child: Text("Log In", style: TextStyle(color: Colors.white)),
      onPressed: () {
        Navigator.push(
          context,
          MaterialPageRoute(builder: (context) => LogInScreen()),
        );
      },
    );
  }



  Widget logoutButton(){
      return RaisedButton(
        color: Color.fromRGBO(58, 66, 86, 1.0),
        child: Text("Log Out", style: TextStyle(color: Colors.white)),
        onPressed: () async {
          await signOutUser();
        }
      );
  }
  Widget signupButton() {
    return RaisedButton(
      color: Color.fromRGBO(58, 66, 86, 1.0),
      child: Text("Sign Up", style: TextStyle(color: Colors.white)),
      onPressed: () {
        Navigator.push(
          context,
          MaterialPageRoute(builder: (context) => SignUpScreen()),
        );
      },
    );
  }
  changeState(value){
    setState(() {
      this.currentUser = value;
    });
  }
}


 

У меня есть функция, которую я написал, называется getSignedInUser() . Если их нет, возвращается значение null. Я новичок в flutter. Указанные выше в комментариях показывают кнопки, которые должны быть видны в определенных случаях. Спасибо за любую помощь.

Ответ №1:

Я бы пошел с этим:

 Widget loginButton() {
  return getSignedInUser() == null
      ? RaisedButton(
          color: Color.fromRGBO(58, 66, 86, 1.0),
          child: Text("Log In", style: TextStyle(color: Colors.white)),
          onPressed: () {
            Navigator.push(
              context,
              MaterialPageRoute(builder: (context) => LogInScreen()),
            );
          },
        )
      : Container();
}
 

Если пользователь вошел в систему, верните пустой контейнер, в противном случае верните кнопку входа. Вы можете сделать то же самое в других функциях, которые возвращают виджет.

Вы также можете обернуть кнопку входа в Opacity виджет и установить opacity значение 0.0, чтобы сделать ее скрытой, но она все равно будет занимать место.

Обновление: я подготовил следующий пример для демонстрации простой страницы входа в систему. getUser Функция имитирует функцию, которая проверяет подлинность пользователя и возвращает имя пользователя (через две секунды), если вход в систему прошел успешно.

 import 'package:flutter/material.dart';

class LoginPage extends StatefulWidget {
  @override
  LoginPageState createState() {
    return new LoginPageState();
  }
}

class LoginPageState extends State<LoginPage> {
  String user;

  Future<String> getUser() {
    return Future.delayed(
      Duration(seconds: 2),
      () {
        return "john";
      },
    );
  }

  void login() async {
    final user = await getUser();
    setState(() {
      this.user = user;
    });
  }

  void logout() {
    setState(() {
      this.user = null;
    });
  }

  Widget _buildLoginButton() {
    return user == null
        ? RaisedButton(
            onPressed: login,
            child: Text("Login"),
          )
        : Container();
  }

  Widget _buildLogoutButton() {
    return (user != null)
        ? RaisedButton(
            onPressed: logout,
            child: Text("Logout"),
          )
        : Container();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Login"),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            _buildLoginButton(),
            _buildLogoutButton(),
          ],
        ),
      ),
    );
  }
}
 

Комментарии:

1. хм, я пробовал обе попытки и столкнулся с дополнительными проблемами. Кажется, что они работают изначально, но функция getSignedInUser() является асинхронной, поэтому изначально она всегда возвращает null . Я попытался сделать свой виджет выхода из системы асинхронным и вызвать signin = await getSignedInUser() и сравнить с signin, но затем мне пришлось заставить его возвращать Future<Widget> вместо просто Widget . Но дочерние элементы виджетов не будут работать с этим. Есть идеи?

2. @Mike1982 Я обновил свой ответ примером. Надеюсь, это поможет.

3. ах, спасибо. логически это имеет смысл, но все мои скрытия кнопок должны выполняться на главном экране, поэтому я попытался написать функцию для изменения состояния на рабочем столе и передать значение null или FirebaseUser. Однако я получаю сообщения об ошибках, в которых говорится, что changeState был вызван для null. Когда я пытался использовать целые числа (1 для входа в систему, 0 для не входа в систему), никакие изменения не применяются. Я обновил свой код из исходного сообщения, чтобы показать еще немного кода и логики. Еще раз спасибо.

Ответ №2:

Хорошо, я нашел обходной путь. В качестве входа используйте мою целевую страницу с кнопкой «Продолжить как гость». Когда я нажимаю войти, это возвращает меня на рабочий стол, но я отправляю значение в конструктор как 1. Если я нажимаю продолжить как гость, он отправляет значение 0. Затем я проверяю, равно ли это значение 0 или 1, чтобы определить, следует ли мне отображать виджеты. У меня возникла еще одна проблема, связанная с formkeys и маршрутами страниц, но я опубликую отдельный вопрос по этому поводу. Спасибо за вашу помощь, ребята