首页 > 解决方案 > SingleChildScrollView 不使用 Stack Widget Flutter 滚动

问题描述

在这里,当我在文本字段中键入时,键盘覆盖了登录按钮。所以我需要在打字时向下滚动到登录按钮。我尝试用 SingleChildScrollView 包装 LayoutBuilder 并尝试在 Stack 中使用 Positioned 小部件,但没有解决我的问题。我在 SingleChildScrollView 中将物理设置为 AlwaysScrollableScrollPhysics() 但它也没有解决问题。我不知道我做错了什么。如果有人可以帮助我解决这个问题,我将不胜感激

这是我的代码

 Material(
  child: SingleChildScrollView(
    child: Stack(
      overflow: Overflow.clip,
      children: <Widget>[
        Image.asset(
          'assets/login-screen-img.jpg'
        ),
        Padding(
          padding: const EdgeInsets.fromLTRB(16.0, 220.0, 16.0, 0),
          child: Card(
            child: Padding(
              padding: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 24.0),
              child: Form(
                //associating global key with the form(It keeps track of the form)
                key: _formKey, 
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
                    Text('Email', style: TextStyle(fontSize: 14.0, color: Colors.grey),),
                    TextFormField(      // email field
                      cursorColor: Colors.brown[500],
                      decoration: InputDecoration(
                        focusedBorder: UnderlineInputBorder(
                          borderSide: BorderSide(color: Colors.brown[500])
                        ),
                        //hintText: 'Enter your Email'
                      ),
                      // validation
                      validator: (email) => email.isEmpty ? 'Enter the email' : null,
                      onChanged: (emailInput) {
                        setState(() {
                          email = emailInput;
                        });
                      },
                    ),
                    SizedBox(height: 16.0),
                    Text('Password', style: TextStyle(fontSize: 14.0, color: Colors.grey),),
                    TextFormField(      // password field
                      cursorColor: Colors.brown[500],
                      decoration: InputDecoration(
                        //hintText: 'Enter your Password'
                        focusedBorder: UnderlineInputBorder(
                          borderSide: BorderSide(color: Colors.brown[500])
                        )
                      ),
                      // validation
                      validator: (password) => password.length < 6 ? 'Password must be more than 6 characters' : null,
                      obscureText: true, // hide when type
                      onChanged: (passwordInput) {
                        setState(() {
                          password = passwordInput;
                        });
                      },
                    ),
                    SizedBox(height: 48.0,),
                    Center(
                      child: RaisedButton(  // login button
                        child: Text('LOG IN', style: TextStyle(fontSize: 16.0, color: Colors.white),),
                        color: Colors.brown[500],
                        shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(25)
                        ),
                        padding: EdgeInsets.fromLTRB(66.0, 16.0, 66.0, 16.0),
                        onPressed: () async {
                          if(_formKey.currentState.validate()) { 
                            // show loading screen
                            setState(() {
                              loading = true;
                            });
    
                            dynamic result = await _auth.signInWithEmailAndPassword(email, password);
    
                            if(result == null) {
                              // stop showing loading screen/widget
                              setState(() {
                                loading = false;
                              });
    
                              // show an error message
                              Fluttertoast.showToast(
                                msg: 'Could not sign in!',
                                toastLength: Toast.LENGTH_SHORT,
                              );
    
                            }
                            
                          }
                        },
                      ),
                    ),
                    SizedBox(height: 24.0),
                    Center(child: Text('Don\'t have and account ?' )),
                    SizedBox(height: 16.0,),
                    Center(
                      child: FlatButton(   // sign up button
                        child: Text('SIGN UP', style: TextStyle(fontSize: 16.0, color: Colors.brown[500] )),
                        onPressed: (){
                          Navigator.push(context, MaterialPageRoute(
                            builder: (context) => SignUp()
                          ));
                        }, 
                      ),
                    )
                  ],
                ),
              ),
            ),
          ),
        )
      ],
    ),
  ),
);

我的用户界面截图

标签: flutterdartflutter-layout

解决方案


在这里,我发现问题在于堆栈的高度。正如评论中提到的@sajithlakmal,堆栈的高度很小,没有什么可以滚动的。但就我而言,我不想让屏幕高度超出屏幕高度,因为这只是一个登录屏幕。我可以通过用 Scaffold 替换 Material 小部件来轻松解决这个问题。Scaffold 主体内部在键入时提供所需的高度并能够向下滚动。

这是工作代码。

Scaffold(
  body: SingleChildScrollView(
      child: Stack(
        overflow: Overflow.visible,
        children: <Widget>[
          Image.asset(
            'assets/login-screen-img.jpg',
             alignment: Alignment.topCenter,
          ),
          Padding(
            padding: const EdgeInsets.fromLTRB(16.0, 220.0, 16.0, 0),
            child: Card(
              child: Padding(
                padding: const EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 24.0),
                child: Form(
                  //associating global key with the form(It keeps track of the form)
                  key: _formKey, 
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    mainAxisSize: MainAxisSize.min,
                    children: <Widget>[
                      Text('Email', style: TextStyle(fontSize: 14.0, color: Colors.grey),),
                      TextFormField(      // email field
                        cursorColor: Colors.brown[500],
                        decoration: InputDecoration(
                          focusedBorder: UnderlineInputBorder(
                            borderSide: BorderSide(color: Colors.brown[500])
                          ),
                          //hintText: 'Enter your Email'
                        ),
                        // validation
                        validator: (email) => email.isEmpty ? 'Enter the email' : null,
                        onChanged: (emailInput) {
                          setState(() {
                            email = emailInput;
                          });
                        },
                      ),
                      SizedBox(height: 16.0),
                      Text('Password', style: TextStyle(fontSize: 14.0, color: Colors.grey),),
                      TextFormField(      // password field
                        cursorColor: Colors.brown[500],
                        decoration: InputDecoration(
                          //hintText: 'Enter your Password'
                          focusedBorder: UnderlineInputBorder(
                            borderSide: BorderSide(color: Colors.brown[500])
                          )
                        ),
                        // validation
                        validator: (password) => password.length < 6 ? 'Password must be more than 6 characters' : null,
                        obscureText: true, // hide when type
                        onChanged: (passwordInput) {
                          setState(() {
                            password = passwordInput;
                          });
                        },
                      ),
                      SizedBox(height: 48.0,),
                      Center(
                        child: RaisedButton(  // login button
                          child: Text('LOG IN', style: TextStyle(fontSize: 16.0, color: Colors.white),),
                          color: Colors.brown[500],
                          shape: RoundedRectangleBorder(
                            borderRadius: BorderRadius.circular(25)
                          ),
                          padding: EdgeInsets.fromLTRB(66.0, 16.0, 66.0, 16.0),
                          onPressed: () async {
                            if(_formKey.currentState.validate()) { // check validation
                              // show loading screen
                              setState(() {
                                loading = true;
                              });
            
                              dynamic result = await _auth.signInWithEmailAndPassword(email, password);
            
                              if(result == null) {
                                // stop showing loading screen/widget
                                setState(() {
                                  loading = false;
                                });
            
                                // show an error message
                                Fluttertoast.showToast(
                                  msg: 'Could not sign in!',
                                  toastLength: Toast.LENGTH_SHORT,
                                );
            
                              }
                              
                            }
                          },
                        ),
                      ),
                      SizedBox(height: 24.0),
                      Center(child: Text('Don\'t have and account ?' )),
                      SizedBox(height: 16.0,),
                      Center(
                        child: FlatButton(   // sign up button
                          child: Text('SIGN UP', style: TextStyle(fontSize: 16.0, color: Colors.brown[500] )),
                          onPressed: (){
                            Navigator.push(context, MaterialPageRoute(
                              builder: (context) => SignUp()
                            ));
                          }, 
                        ),
                      )
                    ],
                  ),
                ),
              ),
            ),
          )
        ],
      ),
    ),
);

推荐阅读