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

问题描述

我会链接以创建一个缩小到内部文本的 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
                  ),),);
  }
}

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

enter image description here

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


这是带有提示的空字段:

enter image description here

没有文字的时候,text field的宽度就是hint的宽度,这就是我想要的。 ✔️


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

enter image description here

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


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

enter image description here

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

如何强制它是内部实际文本的宽度?

解决方法

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

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

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