Flutter - 如何使列屏幕可滚动

Posted

技术标签:

【中文标题】Flutter - 如何使列屏幕可滚动【英文标题】:Flutter - How to make a column screen scrollable 【发布时间】:2019-02-02 20:24:03 【问题描述】:

我正在构建一个带有登录屏幕的颤振应用程序。专注于文本字段时,屏幕溢出,我无法滚动。我试过使用ListView.builder,但这只会给出一个renderBox错误,并且常规的ListView不起作用

小部件结构是这样的

-scafold
   - body
     - container
       - column    
           - form
              - column
                  - textInput
                  - textInput
                  - container    
           - container
              - row      
           - raisedButton

提前谢谢你!!

【问题讨论】:

使用此参考***.com/questions/51997936/flutter-listview-overflow/… 我用 ListView 替换了第一列,它起作用了。如果您更喜欢使用 Listview,请使用 listview 添加示例并将错误粘贴到此处。否则,使用@Zulfiqar 的方式 【参考方案1】:

ListView 解决方案应该可以工作,但在撰写本文时,它受到here 列出的崩溃的影响。另一种在不发生崩溃的情况下实现相同目标的方法是使用SingleChildScrollView

return new Container(
  child: new SingleChildScrollView(
    child: new Column(
      children: <Widget>[
        _showChild1(),
        _showChild2(),
        ...
        _showChildN()
      ]
    )
  )
);

【讨论】:

当我要滚动的列嵌套在另一列中时,此方法对我不起作用。它适用于滚动最外层的列。 只有小部件树中的第一个孩子使列垂直滚动。我想让整个项目滚动 我遇到了一些错误尝试添加``` mainAxisSize: MainAxisSize.min ``` 到你的Column 小部件。此外,如果子小部件是 ListView.builde 添加 shrinkWrap: true【参考方案2】:

试试这个代码:它使用 ListView

    class Home extends StatelessWidget 
  @override
     Widget build(BuildContext context) 
        // TODO: implement build
        return Scaffold(
          body: Center(
            child: ListView(
              shrinkWrap: true,
              padding: EdgeInsets.all(15.0),
              children: <Widget>[
                Center(
                  child: Card(
                    elevation: 8.0,
                    child: Container(
                      padding: EdgeInsets.all(10.0),
                      child: Column(
                        children: <Widget>[
                          TextField(
                            decoration: InputDecoration(
                              prefixIcon: Icon(Icons.person),
                              labelText: "Username or Email",
                            ),
                          ),
                          SizedBox(
                            height: 15.0,
                          ),
                          TextField(
                            decoration: InputDecoration(
                              prefixIcon: Icon(Icons.lock),
                              labelText: "Password",
                            ),
                          ),
                          SizedBox(
                            height: 15.0,
                          ),
                          Material(
                            borderRadius: BorderRadius.circular(30.0),
                            //elevation: 5.0,
                            child: MaterialButton(
                              onPressed: () => ,
                              minWidth: 150.0,
                              height: 50.0,
                              color: Color(0xFF179CDF),
                              child: Text(
                                "LOGIN",
                                style: TextStyle(
                                  fontSize: 16.0,
                                  color: Colors.white,
                                ),
                              ),
                            ),
                          )
                        ],
                      ),
                    ),
                  ),
                ),
                SizedBox(
                  height: 25.0,
                ),
                Row(
                  children: <Widget>[
                    Expanded(child: Text("Don't Have a Account?")),
                    Text("Sign Up",
                        style: TextStyle(
                          color: Colors.blue,
                        )),
                  ],
                ),
              ],
            ),
          ),
          bottomNavigationBar: Padding(
            padding: EdgeInsets.all(10.0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Expanded(
                    child: RaisedButton(
                      padding: EdgeInsets.all(15.0),
                      onPressed: () ,
                      color: Colors.white,
                      shape: RoundedRectangleBorder(
                          borderRadius: BorderRadius.circular(
                            32.0,
                          ),
                          side: BorderSide(color: Color(0xFF179CDF))),
                      child: Text(
                        "SKIP SIGN UP FOR NOW",
                        style:
                        TextStyle(fontSize: 18.0, color: Color(0xFF179CDF)),
                      ),
                    )),
              ],
            ),
          ),
        );
      
    

【讨论】:

shrinkWrap: true 是这个详尽答案中唯一重要的事情【参考方案3】:

有两种简单的方法可以做到这一点。

    将您的Column 包裹在SingleChildScrollView

    SingleChildScrollView(
      child: Column(
        children: [
          Text('First'),
          //... other children
          Text('Last'),
        ],
      ),
    )
    

    使用ListView 而不是Column

    ListView(
      children: [
        Text('First'),
        //... other children
        Text('Last'),
      ],
    )
    

    这种方法使用起来很简单,但是您会失去crossAxisAlignment 等功能以及Column 提供的其他好处,在这种情况下,您可以将您的子小部件包装在Align 中并设置对齐属性。


现在您可能有嵌套的子级,它们可以进一步滚动,在这种情况下,您需要为您的子级提供一个固定的高度,您可以使用SizedBox,仅此而已。

例如:

ListView(
  children: [
    Text('First'),
    SizedBox(
      height: 100,
      child: ListView(...), // nested ScrollView
    ),
    Text('Last'),
  ],
)

【讨论】:

对我来说最完整和最容易理解的答案。 使用SingleChildScrollView 应该是实现这一目标的公认标准方式。 感谢分享此信息。能说说推荐哪一款吗? @Aravin 好吧,这取决于您的用例,如果没有足够的项目并且您想要Column 的某些属性,那就去吧,否则ListView 更好。【参考方案4】:

当我们必须在屏幕上垂直列出小部件并且SingleChildScrollView 小部件为Column 小部件提供滚动功能时使用该列。

当我们使用SingleChildScrollView+Column 时,即使只有少数项目可见,也会呈现整个项目列表。

所以对于包含少量项目的复杂布局,性能提升可能不值得麻烦,在这种情况下我们可以使用SingleChildScrollView。

使用SingleChildScrollViewColumns 使您的屏幕可滚动,并且您可以按照上述方式进行布局

几个优点:

    当需要具有滚动功能的不同小部件时,它会很有用。 对于复杂的布局,当项目较少且性能不是问题时,我们可以使用它(就像每个其他小部件都需要一些不同于其他小部件的修改时)

这是你怎么做的

class MyHome extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    // TODO: implement build
    return Scaffold(
        backgroundColor: Colors.white,
        body: SafeArea(
          bottom: false,
          child: Container(
            padding: EdgeInsets.only(left: 15, right: 15),
            height: double.infinity,
            width: double.infinity,
            child: SingleChildScrollView(
                padding: EdgeInsets.only(bottom: 15),
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.end,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: <Widget>[
                    SizedBox(
                      height: 200.0,
                    ),
                    Card(
                      elevation: 8.0,
                      child: Container(
                        padding: EdgeInsets.all(10.0),
                        child: Column(
                          children: <Widget>[
                            TextField(
                              decoration: InputDecoration(
                                prefixIcon: Icon(Icons.person),
                                labelText: "Username or Email",
                              ),
                            ),
                            SizedBox(
                              height: 15.0,
                            ),
                            TextField(
                              decoration: InputDecoration(
                                prefixIcon: Icon(Icons.lock),
                                labelText: "Password",
                              ),
                            ),
                            SizedBox(
                              height: 30.0,
                            ),
                            MaterialButton(
                                height: 50.0,
                                elevation: 5,
                                minWidth: 300,
                                onPressed: () ,
                                shape: RoundedRectangleBorder(
                                  borderRadius: new BorderRadius.circular(30.0),
                                ),
                                color: Theme.of(context).primaryColor,
                                disabledColor: Theme.of(context)
                                    .primaryColor
                                    .withOpacity(0.50),
                                disabledElevation: 0,
                                child: Text('SIGN IN',
                                    textAlign: TextAlign.center, style: TextStyle(color: Colors.white),))
                          ],
                        ),
                      ),
                    ),
                    SizedBox(
                      height: 25.0,
                    ),
                    Row(
                      children: <Widget>[
                        Expanded(child: Text("Don't Have a Account?")),
                        Text("Sign Up",
                            style: TextStyle(
                              color: Colors.blue,
                            )),
                      ],
                    ),
                    SizedBox(
                      height: 50.0,
                    ),
                    Align(
                      alignment: Alignment.bottomCenter,
                      child: Row(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
                        Text(
                          'New to App?',
                          style: TextStyle(color: Colors.black87),
                        ),
                        SizedBox(
                          width: 5,
                        ),
                        GestureDetector(
                          onTap: () 
                          ,
                          child: Text(
                            "REGISTER", style: TextStyle(
                            color: Colors.blue,
                          )
                          ),
                        ),
                      ]),
                    )
                  ],
                )),
          ),
        ));
  

【讨论】:

你是一个完整的复印机老兄,这次你复制了this的答案。我看到你几乎 95% 的答案都是从别人那里抄来的。 是的,我同意,但我已尝试使用已提出问题的 UI 进行扩展。【参考方案5】:

我们可以使用 Expanded 小部件。它将添加滚动。

return new Expanded(
  child: new SingleChildScrollView(
    child: new Column(
      children: <Widget>[
        _showChild1(),
        _showChild2(),
        ...
        _showChildN()
      ]
    )
  )
);

【讨论】:

【参考方案6】:

将您的列包装在 SingleChildScrollView 中,然后将 SingleChildScrollView 包装在 Center 小部件中以使小部件在列中居中。

Center(
    child: SingleChildScrollView(
        child: Column(
        children: [
            Text('First'),
            //... other children
            Text('Last'),
        ],
    ),
)

【讨论】:

以上是关于Flutter - 如何使列屏幕可滚动的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Flutter 中使屏幕可滚动?

在屏幕上添加按钮而不使用 MaterialApp Flutter

如何在 Flutter 中让 ListView 中的项目覆盖整个屏幕

Flutter 可滚动组件 之 SingleChildScrollView (十五)

Flutter 如何使用 ListView 水平和 GridView 垂直滚动屏幕

Flutter web:如何以步进形式进行水平滚动?