将字段文本缩小到比提示文本更小的宽度

Posted

技术标签:

【中文标题】将字段文本缩小到比提示文本更小的宽度【英文标题】:Shrink a field text to a smaller width than the hintText 【发布时间】:2021-05-27 17:33:06 【问题描述】:

我会链接创建一个TextField,它会缩小到里面的文本。 为此,我使用了this answer,它表示使用IntrinsicWidth 小部件。 效果很好,但是如果我指定hintText,即使用户输入的文字很短,TextField 的宽度也不会小于hintText 的宽度。

这是一个例子:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Container(
            alignment: Alignment.center,
            height: 50,
            width: 300,
            child: Container(
              alignment: Alignment.center,
              padding: EdgeInsets.all(10),
              color: Colors.grey[100],
              child: IntrinsicWidth(
                child: TextField(
                  decoration: InputDecoration(
                    hintText: 'My very very long hint', // Remove it and the text field can be as small as the text inside
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  


这是一个没有提示和小文本的文本字段:

文本域的宽度就是里面文本的宽度,就是我想要的。 ✔️


这是带有提示的空字段:

没有文字的时候,文字字段的宽度就是提示的宽度,这就是我想要的。 ✔️


这里是带有提示的文本字段,提示的长文本:

字段的宽度就是里面文字的宽度,就是我想要的。 ✔️


这是一个带有提示和小文本的非空字段:

如您所见,字段宽度是提示的宽度,而不是里面的文本(这不是我想要的 ❌)。

我怎样才能强制它成为里面实际文本的宽度?

【问题讨论】:

【参考方案1】:

1。将字段宽度设置为文本的宽度,而不是提示

这可以通过使用 TextField 小部件中的 onChanged() 函数来实现,如下所示。

为了能够使用 setState,MyApp 类必须是 StatefulWidget

onChanged: (value) => 
    if (value.isNotEmpty) 
        setState(() 
            hText = '';
        )
     else 
        setState(() 
            hText = 'My very very long hint';
        )
    

2。包装 TextField 的两个容器

我注意到尽管使用了 IntrinsicWidth,但这两个容器是限制 TextField 大小的容器。

如果您使用容器来设置 TextField 可见,另一种方法是设置 TextField 的边框。

Scaffold 的主体可以如下所示:

Center(
    child: IntrinsicWidth(
        child: TextField(
            onChanged: (value) => 
                if (value.isNotEmpty) 
                    setState(() 
                        hText = '';
                    )
                 else 
                    setState(() 
                        hText = 'My very very long hint';
                    )
                
            ,
            decoration: InputDecoration(
                enabledBorder: UnderlineInputBorder(
                    borderSide: BorderSide(color: Colors.black),
                ),
                focusedBorder: UnderlineInputBorder(
                    borderSide: BorderSide(color: Colors.teal),
                ),
                hintText:
                hText, // Remove it and the text field can be as small as the text inside
            ),
        ),
    ),
)

完整代码

import 'package:flutter/material.dart';

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

class MyApp extends StatefulWidget 
  @override
  _MyAppState createState() => _MyAppState();


class _MyAppState extends State<MyApp> 
  String hText = 'My very very long hint';
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: IntrinsicWidth(
            child: TextField(
              onChanged: (value) => 
                if (value.isNotEmpty)
                  
                    setState(() 
                      hText = '';
                    )
                  
                else
                  
                    setState(() 
                      hText = 'My very very long hint';
                    )
                  
              ,
              decoration: InputDecoration(
                enabledBorder: UnderlineInputBorder(
                  borderSide: BorderSide(color: Colors.black),
                ),
                //When the TextFormField is ON focus
                focusedBorder: UnderlineInputBorder(
                  borderSide: BorderSide(color: Colors.teal),
                ),
                hintText:
                    hText, // Remove it and the text field can be as small as the text inside
              ),
            ),
          ),
        ),
      ),
    );
  

【讨论】:

【参考方案2】:

您可以根据TextEditingController 的内容有条件地更改hintText

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';

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

class MyApp extends HookWidget 
  @override
  Widget build(BuildContext context) 
    final _controller = useTextEditingController();
    final _editing = useState(false);
    _controller.addListener(() => _editing.value = _controller.text.isNotEmpty);
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Container(
            alignment: Alignment.center,
            width: 300,
            child: Container(
              alignment: Alignment.center,
              padding: EdgeInsets.all(10),
              color: Colors.grey[100],
              child: Column(
                children: [
                  IntrinsicWidth(
                    child: TextFormField(
                      controller: _controller,
                      decoration: InputDecoration(
                        hintText: _editing.value
                            ? '' // empty hintText if field is not empty
                            : 'My very very long hint',
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  

【讨论】:

以上是关于将字段文本缩小到比提示文本更小的宽度的主要内容,如果未能解决你的问题,请参考以下文章

当我缩小屏幕时,某些列文本在 Td 元素内不可见

UITextField 的宽度永远不会小于占位符文本的宽度

ios:文本在 iPhone 5S 及更早版本(4 英寸及更小的设备)上无法正确换行

字段集中的溢出和文本溢出

为啥弹性项目不缩小超过内容大小?

对于宽度较小的手机,文本超出范围