提取的小部件内的颤振滑块

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)。这就是 GestureDetectoronTap 参数所期望的。传递任何其他类型的函数不是您想要做的事情,因为它会破坏您的应用程序。输入参数时尽可能具体。您可以将此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。如果您对它们不熟悉,我敦促您阅读它们,它们非常重要。正如您正确地注意到的那样,您无法在子小部件内执行逻辑;您想将其保留在其父级中。您可以通过创建这些回调函数来管理它。

您在父级中创建回调函数。 您将函数传递给您的子小部件。 一旦触发,就会在父级内部执行一个函数。孩子只知道它必须触发这个函数,但所有的逻辑都被它隐藏了。

【讨论】:

以上是关于提取的小部件内的颤振滑块的主要内容,如果未能解决你的问题,请参考以下文章

带有刻度文本标签的 Qt 滑块小部件

将范围滑块小部件移植到 PyQt5

VTK Iso Slider 不工作或不显示滑块小部件

如何创建自定义颤振 sdk 小部件,重建颤振和使用新的小部件

滚动小部件内的颤振滚动小部件

我调用的小部件未显示在颤振列中