我想构建一个笔记应用程序,因为我的
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
════════════════════════════════════════════════════════════════════════════════
您遇到的错误与在
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 ?? ''))
],
),
],
),
我想这可能有用
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)"),
],
);
****注意:这主要是针对多行文本字段,所以我注释了一些代码...请查看并相应地更改它
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)),
],
);