Flutter 展开/占用 TextFormField 以填充屏幕的其余部分

问题描述 投票:0回答:7

我有一个带有一些 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
7个回答
3
投票

我稍微编辑了你的代码。但是没用。请参考以下代码。我会尝试解释我的理解在代码下面。

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),这看起来像是占据了屏幕。但它不是动态的(不会根据屏幕尺寸/屏幕方向改变)

2
投票

我找到了解决方案,也许它可以帮助某人。您可以创建 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,
                    ),
                  ),
                ),

2
投票
expands: true,

解决您的问题:) 这是扩展文本字段的代码:

TextField(
    maxLines: null,
    expands: true,
    textAlignVertical: TextAlignVertical.top,
    keyboardType: TextInputType.multiline,
)

1
投票

您还可以在使用

contentPadding
addPostFrameCallback
渲染小部件后设置
initState()
。 但是您必须根据上述所有小部件的位置和高度手动计算新高度。

例子:

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",
                      ),
                    ),
                  ),
                ]),
              ),
            ),
          ],
        ),
      ),
    );
  }
}


1
投票

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

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

0
投票

TextFormField 包含 expands 属性。

Expanded(
  child: TextFormField(
    //...
    maxLines: null,
    expands: true,
)),

当您将

expands
属性设置为true时,您必须将
maxLines
设置为
null
。然后,为了让它工作,将
TextFormField
包裹在
Expanded
中。


0
投票

很简单

TextFormField(
    expands: true,  // add this line
    minLines: null, // add this line
    maxLines: null, // add this line
    decoration: InputDecoration(
      // if you want to change text form field background color  
      // add this two lines
      fillColor: Theme.of(context).colorScheme.background,
      filled: true,
    ),
  )
© www.soinside.com 2019 - 2024. All rights reserved.