提取的小部件内的颤振滑块
Posted
技术标签:
【中文标题】提取的小部件内的颤振滑块【英文标题】:Flutter Slider inside a Extracted Widget 【发布时间】:2021-11-13 02:43:40 【问题描述】:好的,我正在尝试更具体。我的目标是将部分代码分成单独的小部件,以便主树尽可能保持干净。
在以下示例中,我有一个 StatefulWidget 中的主树。我已经成功地将带有按钮的容器转换为带有Extract to Widget的自己的小部件。按钮的 setState 通过 constructor 起作用。
现在我想对第二个容纳滑块的容器做同样的事情。但我不知道如何使用构造函数处理 Slider onChanged setState,因为 setState 在提取的 Widget 中不起作用。
这是代码示例,其中工作按钮作为提取的小部件,滑块仍在主树内。
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget
@override
Widget build(BuildContext context)
return MaterialApp(
home: MyStfl(),
);
class MyStfl extends StatefulWidget
@override
_MyStflState createState() => _MyStflState();
class _MyStflState extends State<MyStfl>
double sliderPos = 0.0;
@override
Widget build(BuildContext context)
return Scaffold(
body: Container(
decoration: BoxDecoration(
color: Color(0x80061A28),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: MyCardA(
aktion: ()
setState(()
print('Button Pressed');
);
,
),
),
Expanded(
child: Container(
child: Slider(
divisions: 48,
value: sliderPos,
min: 0.0,
max: 24.0,
onChanged: (double newValue)
setState(
()
sliderPos = double.parse(newValue.toStringAsFixed(1));
print(sliderPos);
,
);
,
),
),
),
],
),
),
);
class MyCardA extends StatelessWidget
MyCardA(this.aktion);
final Function aktion;
@override
Widget build(BuildContext context)
return Container(
margin: EdgeInsets.all(20.0),
padding: EdgeInsets.all(20.0),
color: Color(0x80125889),
child: GestureDetector(
onTap: aktion,
child: Text(
'MY BUTTON',
style: TextStyle(
color: Color(0xFF3D3939),
fontSize: 22.0,
),
),
),
);
【问题讨论】:
在无状态下,setState
不起作用,它在有状态管理下起作用
我用完整的代码和更具体的描述更新了问题
【参考方案1】:
首先,您要在CardA
组件中更改一件事。不要将aktion
参数输入为Function
(这是非常通用的),而应该给它一个void Function()
的类型,说:它是一个什么都不返回的函数(void)。这就是 GestureDetector
的 onTap
参数所期望的。传递任何其他类型的函数不是您想要做的事情,因为它会破坏您的应用程序。输入参数时尽可能具体。您可以将此void Function()
类型缩短为VoidCallback
。都是一样的。
我也做了参数required
。这不是必需的,但这是你想要的(我认为)。如果您希望能够发出此参数,请去掉 required
关键字并将您的 aktion
键入为 void Function()?
。 ?
表示您可以通过void Function()
或null
。
class MyCardA extends StatelessWidget
MyCardA(required this.aktion);
final void Function() aktion;
@override
Widget build(BuildContext context)
return Container(
margin: EdgeInsets.all(20.0),
padding: EdgeInsets.all(20.0),
color: Color(0x80125889),
child: GestureDetector(
onTap: aktion,
child: Text(
'MY BUTTON',
style: TextStyle(
color: Color(0xFF3D3939),
fontSize: 22.0,
),
),
),
);
对于“MyCardB”,您需要设置一个带有参数的回调函数。这有点复杂。
Slider
组件有一个onChanged
参数,当滑块位置改变时触发。这会给你一个double
(新职位)并允许你用它做事。输入为void Function(double)
。我们有一个函数,它获取 double
作为参数,它什么也不返回 (void
)。
您可以在下面的自定义组件中看到它的外观。
class MyCardB extends StatelessWidget
const MyCardB(
required this.sliderPos,
required this.onChanged,
);
final double sliderPos;
final void Function(double) onChanged;
@override
Widget build(BuildContext context)
return Container(
child: Slider(
divisions: 48,
value: sliderPos,
min: 0.0,
max: 24.0,
onChanged: onChanged,
),
);
你在你的主要组件中使用这个新组件如下。
Expanded(
child: MyCardB(
sliderPos: sliderPos,
onChanged: (double newValue)
setState(
()
sliderPos = double.parse(newValue.toStringAsFixed(1));
,
);
,
),
),
长话短说,您想使用callback functions
。如果您对它们不熟悉,我敦促您阅读它们,它们非常重要。正如您正确地注意到的那样,您无法在子小部件内执行逻辑;您想将其保留在其父级中。您可以通过创建这些回调函数来管理它。
您在父级中创建回调函数。 您将函数传递给您的子小部件。 一旦触发,就会在父级内部执行一个函数。孩子只知道它必须触发这个函数,但所有的逻辑都被它隐藏了。
【讨论】:
以上是关于提取的小部件内的颤振滑块的主要内容,如果未能解决你的问题,请参考以下文章