【问题标题】:Flutter Expand/Occupy TextFormField to Fill Rest of ScreenFlutter 扩展/占用 TextFormField 以填充屏幕的其余部分
【发布时间】:2019-04-01 08:07:25
【问题描述】:

我有一个带有一些 TextFormField 的表单,我想扩展最后一个 TextFormField 以占据屏幕的其余部分。最后一个 TextFormField 可以有多行文本。

我无法做到这一点,并尝试了SizedBox.expand()Expanded 小部件,但没有运气。

下面是当前代码:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @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 GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Text(
              "What is this new classroom?"
            ),
            SizedBox(height: 8.0,),
            Expanded(
              child: Form(
              key: _formKey,
              child: ListView(
                padding: EdgeInsets.all(8.0),
                children: <Widget>[
                  Container(
                    padding: EdgeInsets.symmetric(vertical: 8.0),
                    child: TextFormField(
                      decoration: InputDecoration(
                        border: OutlineInputBorder(),
                        labelText: "Classroom Name",
                        hintText: "What's name of the new classroom?",
                      ),
                    )
                  ),
                  SizedBox(height: 8.0,),
                  Container(
                    padding: EdgeInsets.symmetric(vertical: 8.0),
                    child: TextFormField(
                      decoration: InputDecoration(
                        border: OutlineInputBorder(),
                        labelText: "Description",
                        hintText: "Description of the new classroom",
                      ),
                      //maxLines: 5,
                    ),
                  ),
                ]
              ),
            ),
          ),
        ],
      ),
    ),
    );
  }
}

【问题讨论】:

    标签: flutter flutter-layout


    【解决方案1】:

    我稍微编辑了您的代码。但是没有用。请参考以下代码。我将尝试在代码下方解释我的理解

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @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 GlobalKey<FormState> _formKey = GlobalKey<FormState>();
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Padding(
            padding: const EdgeInsets.all(16.0),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Text("What is this new classroom?"),
                SizedBox(
                  height: 8.0,
                ),
                Expanded(
                    child: Form(
                  key: _formKey,
                  child: Column(children: <Widget>[
                    Container(
                        padding: EdgeInsets.symmetric(vertical: 8.0),
                        child: TextFormField(
                          decoration: InputDecoration(
                            border: OutlineInputBorder(),
                            labelText: "Classroom Name",
                            hintText: "What's name of the new classroom?",
                          ),
                        )),
                    SizedBox(
                      height: 8.0,
                    ),
                    Expanded(
                      child: Container(
                        padding: EdgeInsets.symmetric(vertical: 8.0),
                        child: TextFormField(
                          maxLines: null,
                          decoration: InputDecoration(
                            border: OutlineInputBorder(),
                            labelText: "Description",
                            hintText: "Description of the new classroom",
                          ),
                        ),
                      ),
                    ),
                  ]),
                )),
              ],
            ),
          ),
        );
      }
    }
    

    我用您的代码检查了视图。 TextField 里面的 TextFormField 没有占据屏幕的其余部分。所以我编辑让TextField 拥有屏幕的其余部分。上面的代码就是这样做的。查看检查视图

    但是有InputDecorator(它是我们的TextField 的孩子)绘制了边界线。在我们的例子中,它根据内容绘制边界线。

    可能的解决方法是:

    1. maxLines = null 将把 TextField 扩展为内容组。但初始视图将是一行。
    2. 给出固定的maxLines(如 10 或 20),这看起来像是占据了屏幕。但它不是动态的(不会根据屏幕尺寸/屏幕方向而变化)

    【讨论】:

    • 这两种方法都有其局限性,但我想不出更好的办法。 +1 使用检查器!
    【解决方案2】:

    您还可以在小部件渲染后使用addPostFrameCallbackinitState() 中设置contentPadding。 但是您必须根据上述所有小部件的位置和高度手动计算新高度。

    例子:

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      // This widget is the root of your application.
      @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 GlobalKey<FormState> _formKey = GlobalKey<FormState>();
      final _tffKey1 =
          GlobalKey();
      final _tffKey2 = GlobalKey();
      final _scaffoldKey = GlobalKey();
      final _textKey = GlobalKey();
      double _height = 0;
    
      //Set callback that will be called after widgets are rendered.
      @override
      void initState() {
        super.initState();
        WidgetsBinding.instance.addPostFrameCallback((_) {
          final RenderBox scaffoldKeyBox = _scaffoldKey.currentContext.findRenderObject();
          final RenderBox tffBox = _tffKey1.currentContext.findRenderObject();
          final RenderBox textBox = _textKey.currentContext.findRenderObject();
          final tffPos = tffBox.localToGlobal(Offset.zero);
          final textPos = textBox.localToGlobal(Offset.zero);
    
          //Calculate widget's height.
          _height = (scaffoldKeyBox.size.height -
              (tffBox.size.height + tffPos.dy) -
              (textBox.size.height + textPos.dy));
    
          setState(() {});
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          key: _scaffoldKey,
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: Padding(
            padding: const EdgeInsets.all(8.0),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: <Widget>[
                Text(
                  "What is this new classroom?",
                  key: _textKey,
                ),
                SizedBox(
                  height: 8.0,
                ),
                Expanded(
                  child: Form(
                    key: _formKey,
                    child:
                        ListView(padding: EdgeInsets.all(8.0), children: <Widget>[
                      Container(
                          padding: EdgeInsets.symmetric(vertical: 8.0),
                          child: TextFormField(
                            key: _tffKey1,
                            decoration: InputDecoration(
                              border: OutlineInputBorder(),
                              labelText: "Classroom Name",
                              hintText: "What's name of the new classroom?",
                            ),
                          )),
                      Container(
                        padding: EdgeInsets.symmetric(vertical: 8.0),
                        child: TextFormField(
                          key: _tffKey2,
                          decoration: InputDecoration(
                            contentPadding: EdgeInsets.only(left: 8, top: _height), // Set new height here
                            border: OutlineInputBorder(),
                            labelText: "Description",
                            hintText: "Description of the new classroom",
                          ),
                        ),
                      ),
                    ]),
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }
    

    【讨论】:

      【解决方案3】:

      我知道这有点晚了,但答案已发布here。 您只需要以下内容

      TextField(
        keyboardType: TextInputType.multiline,
        maxLines: whatever,
      )
      

      【讨论】:

        【解决方案4】:

        我找到了解决方案,也许它可以帮助某人。您可以创建 Container 或其他具有与 TextField 相同的边框的小部件,并使其扩展以填充整个屏幕,并使用 Stack 小部件将 TextField 放入 maxLines: null 且无边框。

        [编辑] 它也可以在没有 Stack 小部件的情况下工作。这是我的代码

        Expanded(
                          child: Material(
                            borderRadius: BorderRadius.circular(10),                      
                            color: Colors.white,
                            child: TextField(                         
                              decoration: InputDecoration(
                                border: InputBorder.none,  
                                hintText: "Description",                         
                              ),
                              keyboardType: TextInputType.multiline,
                              maxLines: null,
                            ),
                          ),
                        ),
        

        【讨论】:

          猜你喜欢
          • 2021-04-05
          • 1970-01-01
          • 2019-07-17
          • 2011-12-10
          • 1970-01-01
          • 2016-08-12
          • 2013-07-25
          • 1970-01-01
          • 2016-06-13
          相关资源
          最近更新 更多