如何在 flutter 中制作多行文本字段?

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

我想构建一个笔记应用程序,因为我的

noteapp
的每个笔记实体都有一个以正文名称命名的属性,即它是一个字符串。我的问题是,在我的 AddOrUpdateScreen 中,如何制作一个
textfield
,如果我添加更多文本,它应该获得更多空间,根据其内容获取大小。我在 stackOverFlow 中搜索了他们建议设置
maxLines: null
expands: true
的其他类似问题,我已经完成了这些问题,但没有一个最适合该应用程序。

这是我的实际代码

AddOrUpdateScreen

import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:note_app_last_one/config/routes/my_router.dart';
import 'package:note_app_last_one/features/label/domain/entity/labelx.dart';
import 'package:note_app_last_one/features/note/domain/entities/notex.dart';
import 'package:note_app_last_one/features/note/presetation/riverpod/providers.dart';
import 'package:timeago/timeago.dart' as timeago;

class AddOrUpdateNotePage extends ConsumerStatefulWidget {
  final Notex note;
  final Labelx? label;

  const AddOrUpdateNotePage({super.key, this.label, required this.note});

  @override
  ConsumerState<ConsumerStatefulWidget> createState() =>
      _AddOrUpdateNotePageState();
}

class _AddOrUpdateNotePageState extends ConsumerState<AddOrUpdateNotePage> {
  late TextEditingController desCTL;

  late String body;

  @override
  void initState() {
    super.initState();
    desCTL = TextEditingController(text: widget.note.body ?? '');
    body = desCTL.text;
  }

  @override
  void dispose() {
    desCTL.dispose();
    body = '';
    super.dispose();
  }

  Notex addNote() {
    if (widget.label != null) {
      widget.note.labels.add(widget.label!);
    }
    widget.note.body = body;

    Notex notex = ref.read(noteCRUDProvider).addOrUpdateNotex(widget.note);
    return notex;
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        elevation: 0,
        shadowColor: null,
        leading: IconButton(
          icon: const Icon(Icons.arrow_back_ios),
          onPressed: () {
            addNote();
            GoRouter.of(context).pop();
          },
        ),
      ),
      body: Column(
        children: [
          SizedBox(
            child: TextField(
              expands: true,
              maxLines: null,
              onChanged: (newDes) {
                setState(() {
                  body = newDes;
                });
              },
              controller: desCTL,
              keyboardType: TextInputType.multiline,
              decoration: const InputDecoration(
                hintText: 'description',
              ),
            ),
          ),
          Wrap(
            children: [
              for (final label in widget.note.labels)
                Chip(label: Text(label.name ?? ''))
            ],
          ),
        ],
      ),
      persistentFooterAlignment: AlignmentDirectional.topStart,
      persistentFooterButtons: [
        IconButton(
            icon: const Icon(Icons.library_add_outlined),
            onPressed: () {
              final note = addNote();
              context.push('/${AppRoutes.addLabelsToNote}', extra: note);
            }),
        const Spacer(),
        Text(timeago.format(widget.note.updatedTime)),
      ],
    );
  }
}

但问题是,当我运行它时,会发生这些错误:

═══════ Exception caught by widgets library ═══════════════════════════════════
The following assertion was thrown while applying parent data.:
Incorrect use of ParentDataWidget.

The ParentDataWidget Expanded(flex: 1) wants to apply ParentData of type FlexParentData to a RenderObject, which has been set up to accept ParentData of incompatible type _OverflowBarParentData.

Usually, this means that the Expanded widget has the wrong ancestor RenderObjectWidget. Typically, Expanded widgets are placed directly inside Flex widgets.
The offending Expanded is currently placed inside a OverflowBar widget.

The ownership chain for the RenderObject that received the incompatible parent data was:
  SizedBox.shrink ← Expanded ← Spacer ← OverflowBar ← Align ← Padding ← Container ← IntrinsicHeight ← MediaQuery ← Padding ← ⋯
When the exception was thrown, this was the stack
#0      RenderObjectElement._updateParentData.<anonymous closure>
framework.dart:6230
#1      RenderObjectElement._updateParentData
framework.dart:6247
#2      RenderObjectElement.attachRenderObject
framework.dart:6270
#3      RenderObjectElement.mount
framework.dart:6154
#4      SingleChildRenderObjectElement.mount
framework.dart:6433
...     Normal element mounting (13 frames)
#17     Element.inflateWidget
framework.dart:4182
#18     MultiChildRenderObjectElement.inflateWidget
framework.dart:6569  74     Element.inflateWidget
framework.dart:4182
#75     MultiChildRenderObjectElement.inflateWidget
framework.dart:6569
#76     MultiChildRenderObjectElement.mount
framework.dart:6581
...     Normal element mounting (332 frames)
#408    Element.inflateWidget
framework.dart:4182
#409    MultiChildRenderObjectElement.inflateWidget
framework.dart:6569
#410    Element.updateChild
framework.dart:3707
#411    Element.updateChildren
framework.dart:3894
#412    MultiChildRenderObjectElement.update
framework.dart:6594
#413    Element.updateChild
framework.dart:3685
#414    ComponentElement.performRebuild
framework.dart:5322
#415    StatefulElement.performRebuild
framework.dart:5462
#416    Element.rebuild
framework.dart:5016
#417    StatefulElement.update
framework.dart:5485
#418    Element.updateChild
framework.dart:3685
#419    ComponentElement.performRebuild
framework.dart:5322
#420    Element.rebuild
framework.dart:5016
#421    ProxyElement.update
framework.dart:5628
#422    Element.updateChild
framework.dart:3685
#423    ComponentElement.performRebuild
framework.dart:5322
#424    Element.rebuild
framework.dart:5016
#425    ProxyElement.update
framework.dart:5628
#426    _InheritedNotifierElement.update
inherited_noti

最后这些错误也发生了,并且至少在那时重复了:

════════ Exception caught by rendering library ═════════════════════════════════

BoxConstraints forces an infinite height.

The relevant error-causing widget was

TextField

add_or_update_note_page.dart:70

════════════════════════════════════════════════════════════════════════════════

════════ Exception caught by rendering library ═════════════════════════════════

RenderBox was not laid out: \_RenderDecoration#f161d relayoutBoundary=up8 NEEDS-PAINT NEEDS-COMPOSITING-BITS-UPDATE

'package:flutter/src/rendering/box.dart':

box.dart:1

Failed assertion: line 1965 pos 12: 'hasSize'

The relevant error-causing widget was

TextField

add_or_update_note_page.dart:70

════════════════════════════════════════════════════════════════════════════════
flutter dart textfield
3个回答
0
投票

您遇到的错误与在

TextField
中使用
SizedBox
小部件以及
expands: true
maxLines: null
相关。这些属性会导致布局计算中的冲突。

要创建根据其内容增长的文本字段,您可以使用不同的方法,使用

Expanded
中的
Column
小部件。

body
替换为:

Column(
  children: [
    Expanded(
      child: TextField(
        maxLines: null,
        controller: desCTL,
        keyboardType: TextInputType.multiline,
        decoration: const InputDecoration(
          hintText: 'description',
        ),
      ),
    ),
    Wrap(
      children: [
        for (final label in widget.note.labels)
          Chip(label: Text(label.name ?? ''))
      ],
    ),
  ],
),

0
投票

我想这可能有用

return Scaffold(
      appBar: AppBar(
        elevation: 0,
        shadowColor: null,
        leading: IconButton(
          icon: const Icon(Icons.arrow_back_ios),
          onPressed: () {
            // addNote();
            // GoRouter.of(context).pop();
          },
        ),
      ),
      body: Column(
        children: [
          TextField(
            // expands: true,
            maxLines: null,
            onChanged: (newDes) {
              setState(() {
                body = newDes;
              });
            },
            controller: desCTL,
            keyboardType: TextInputType.multiline,
            decoration: const InputDecoration(
              hintText: 'description',
            ),
          ),
          /*     Wrap(
            children: [
              for (final label in widget.note.labels)
                Chip(label: Text(label.name ?? ''))
            ],
          ), */
        ],
      ),
      persistentFooterAlignment: AlignmentDirectional.topStart,
      persistentFooterButtons: [
        IconButton(
            icon: const Icon(Icons.library_add_outlined),
            onPressed: () {
              /*  final note = addNote();
              context.push('/${AppRoutes.addLabelsToNote}', extra: note); */
            }),
        // const Spacer(),
        Text("timeago.format(widget.note.updatedTime)"),
      ],
    );

****注意:这主要是针对多行文本字段,所以我注释了一些代码...请查看并相应地更改它


0
投票
  • Expanded widget
    里面的
    TextField
    不正确。
    Expanded widget
    应直接放置在
    Flex widget
    内,但在您的代码中,它放置在
    OverflowBar widget
    内。
  • 取下
    Expanded widget
    并用
    TextField
    包裹
    Flexible widget
Column(
  children: [
    Flexible(
      child: TextField(
        expands: true,
        maxLines: null,
        onChanged: (newDes) {
          setState(() {
            body = newDes;
          });
        },
        controller: desCTL,
        keyboardType: TextInputType.multiline,
        decoration: const InputDecoration(
          hintText: 'description',
        ),
      ),
    ),
    Wrap(
      children: [
        for (final label in widget.note.labels)
          Chip(label: Text(label.name ?? ''))
      ],
    ),
  ],
),
  • 通过使用
    Flexible widget
    TextField
    将占用可用空间并根据其内容垂直扩展

Edit
:要获得带有
multiline TextField
persistent footer buttons
的 UI,您可以将包含 TextField 的 Column 和 Wrap 小部件包装在
SingleChildScrollView
内。当内容超出可用空间时,这将启用滚动。

Scaffold(
  appBar: AppBar(
    elevation: 0,
    shadowColor: null,
    leading: IconButton(
      icon: const Icon(Icons.arrow_back_ios),
      onPressed: () {
        addNote();
        GoRouter.of(context).pop();
      },
    ),
  ),
  body: SingleChildScrollView(
    child: Column(
      children: [
        SizedBox(
          child: TextField(
            expands: true,
            maxLines: null,
            onChanged: (newDes) {
              setState(() {
                body = newDes;
              });
            },
            controller: desCTL,
            keyboardType: TextInputType.multiline,
            decoration: const InputDecoration(
              hintText: 'description',
            ),
          ),
        ),
        Wrap(
          children: [
            for (final label in widget.note.labels)
              Chip(label: Text(label.name ?? ''))
          ],
        ),
      ],
    ),
  ),
  persistentFooterButtons: [
    IconButton(
      icon: const Icon(Icons.library_add_outlined),
      onPressed: () {
        final note = addNote();
        context.push('/${AppRoutes.addLabelsToNote}', extra: note);
      },
    ),
    const Spacer(),
    Text(timeago.format(widget.note.updatedTime)),
  ],
);

© www.soinside.com 2019 - 2024. All rights reserved.