gpt4 book ai didi

android - 有没有办法让复合小部件在 flutter 中继承它所组成的小部件的属性?

转载 作者:行者123 更新时间:2023-12-05 04:25:41 25 4
gpt4 key购买 nike

我创建了一个小部件,根据其 FocusNode 的焦点,它可以变成 TextFieldText。它运行良好并且here is the code (这里没有包括它,因为它很大)。

问题是,TextTextField 确实有很多参数来设置它们的样式,我发现将所有这些参数复制到我的新混合小部件只是将它们传递给新的 build 方法中的这两个小部件,而不对它们进行任何其他操作。

例如 TextField 在其构造函数中有超过 50 个参数,这是将它与另一个小部件组合并仍然获得所有这些选项来设置 TextField 样式的唯一方法,是通过将这些参数中的每一个复制到我的构造函数中,然后除了将它们传递给 TextField?

之外不对它们做任何事情

那么是否有某种设计模式或某种解决方案可以让这两个小部件的参数在新小部件的构造函数中可用?

注意:请参阅 comment ofM. Azyoksul on Gunter's comment here也可以获取更多上下文。

问题的最小示例:

// this widget is from external library (not under my control)
class WidgetA extends StatelessWidget {
// very long list of fields
A1 a1;

A2 a2;

... (long list of fields)

// constructor
WidgetA(this.a1, this.a2, ...);

}

// this widget is from external library
class WidgetB extends StatelessWidget {
// very long list of fields
B1 b1;

B2 b2;

... (long list of fields)

// constructor
WidgetB(this.b1, this.b2, ...);

}


// now this is the widget I want to create
class HybridWidget extends StatelessWidget {

// time consuming: I copy all the fields of WidgetA and
// WidgetB into the new constructor just to pass them as they are without doing anything else useful on them
A1 a1;
A2 a2;
...


B1 b1;
B2 b2;
...

// the new constructor: (not optimal at all)
HybridWidget(this.a1,this.a2,...,this.b1,this.b2,...);

@override
Widget build(BuildContext context) {
// for example:
if(some condition)
return Container(child:WidgetA(a1,a2, ...),...); <--- here is the problem, I am not doing anything other than passing the "styling" parameters as they were passed to me, alot of copy/paste
if(other condition)
return Container(Widget2(b1,b2, ... ),...); <--- and here is the same problem

//... other code
}
}

最佳答案

构建器模式可能会起作用(不确定这是不是正确的术语)。

首先定义我们的函数签名:

typedef TextBuilder = Widget Function(String text);
typedef TextFieldBuilder = Widget Function(TextEditingController, FocusNode);

那些将在您的 DoubleStatetext 中使用...

DoubleStateText(
initialText: 'Initial Text',
textBuilder: (text) => Text(text, style: TextStyle(fontSize: 18)),
textFieldBuilder: (controller, focusNode) =>
TextField(controller: controller, focusNode: focusNode, cursorColor: Colors.green,)
),

...所以我们没有将所有参数传递给 DoubleStateText,而是传递给它包装 TextTextField 的构建器(函数)我们想要的所有参数。然后 DoubleStateText 只调用构建器而不是创建 Text/TextField 本身。

DoubleStateText 的更改:

class DoubleStateText extends StatefulWidget {
final String Function()? onGainFocus;

final String? Function(String value)? onLoseFocus;

final String initialText;

// NEW ==================================================
final TextBuilder textBuilder;

// NEW ==================================================
final TextFieldBuilder textFieldBuilder;

final ThemeData? theme;

final InputDecoration? inputDecoration;

final int? maxLines;

final Color? cursorColor;

final EdgeInsets padding;

final TextStyle? textStyle;

const DoubleStateText({
Key? key,
this.onGainFocus,
this.onLoseFocus,
required this.initialText,
required this.textBuilder, // NEW ==================================================
required this.textFieldBuilder, // NEW ==================================================
this.theme,
this.inputDecoration,
this.maxLines,
this.cursorColor,
this.padding = EdgeInsets.zero,
this.textStyle,
}) : super(key: key);

@override
State<DoubleStateText> createState() => _DoubleStateTextState();
}

class _DoubleStateTextState extends State<DoubleStateText> {
bool _isEditing = false;
late final TextEditingController _textController;
late final FocusNode _focusNode;
late final void Function() _onChangeFocus;

@override
void initState() {
super.initState();

_textController = TextEditingController(text: widget.initialText);
_focusNode = FocusNode();

// handle Enter key event when the TextField is focused
_focusNode.onKeyEvent = (node, event) {
if (event.logicalKey == LogicalKeyboardKey.enter) {
setState(() {
String? text = widget.onLoseFocus?.call(_textController.text);
_textController.text = text ?? widget.initialText;
_isEditing = false;
});
return KeyEventResult.handled;
}
return KeyEventResult.ignored;
};

// handle TextField lose focus event due to other reasons
_onChangeFocus = () {
if (_focusNode.hasFocus) {
String? text = widget.onGainFocus?.call();
_textController.text = text ?? widget.initialText;
}
if (!_focusNode.hasFocus) {
setState(() {
String? text = widget.onLoseFocus?.call(_textController.text);
_textController.text = text ?? widget.initialText;
_isEditing = false;
});
}
};
_focusNode.addListener(_onChangeFocus);
}

@override
void dispose() {
_textController.dispose();
_focusNode.removeListener(_onChangeFocus);
_focusNode.dispose();
super.dispose();
}

@override
Widget build(BuildContext context) {
Widget child;
if (!_isEditing) {
child = InkWell(
onTap: () {
setState(() {
_isEditing = true;
_focusNode.requestFocus();
});
},
//child: Text(_textController.text, style: widget.textStyle),
// NEW: use the builders ==========================================
child: widget.textBuilder(_textController.text));
} else {
// NEW: use the builders ==========================================
child = widget.textFieldBuilder(_textController, _focusNode);
/*child = TextField(
focusNode: _focusNode,
controller: _textController,
decoration: widget.inputDecoration,
maxLines: widget.maxLines,
cursorColor: widget.cursorColor,
);*/
}

child = Padding(
padding: widget.padding,
child: child,
);

child = Theme(
data: widget.theme ?? Theme.of(context),
child: child,
);

return child;
}
}

下面是如何使用上述内容的示例:

typedef TextBuilder = Widget Function(String text);
typedef TextFieldBuilder = Widget Function(TextEditingController, FocusNode);


class CompositeWidgetContent extends StatefulWidget {
@override
State<CompositeWidgetContent> createState() => _CompositeWidgetContentState();
}

class _CompositeWidgetContentState extends State<CompositeWidgetContent> {
@override
Widget build(BuildContext context) {
return Center(
child: Container(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SomeOtherFocusable(),
SizedBox(
height: 20,
),
DoubleStateText(
initialText: 'Initial Text',
textBuilder: (text) =>
Text(text, style: TextStyle(fontSize: 18)),
textFieldBuilder: (controller, focusNode) => TextField(
controller: controller,
focusNode: focusNode,
cursorColor: Colors.green,
)),
],
),
),
);
}
}

请注意 (text)(controller, focusNode) 未在 _CompositeWidgetContentState 中的任何位置定义。

那些不是由最终用户/客户创建/使用的。

这些是在 DoubleStateText 中创建的。

关于android - 有没有办法让复合小部件在 flutter 中继承它所组成的小部件的属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73185138/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com