如何在一个滑块上添加多个滑块? #扑

Posted

技术标签:

【中文标题】如何在一个滑块上添加多个滑块? #扑【英文标题】:how to add multiple sliders on one slider? #Flutter 【发布时间】:2021-12-31 00:09:00 【问题描述】:

我想在一个滑块中添加多个滑块。如果你不清楚我在问什么,请参考下图

我希望这三个方块可以滑动并获取它们的值。 我做了一些搜索,找不到任何颤振小部件或支持的插件。

我尝试使用堆栈并在同一位置使用多个 Slider 小部件,但它也无法正常工作。 (我知道这不是一个好方法。)

我怎样才能做到这一点。在同一行上有多个滑块并获取值。 非常感谢任何帮助或想法。

【问题讨论】:

【参考方案1】:

Stack 与三个滑块一起使用不起作用,因为它被重叠了。

我让Slider3X 感到好奇。这里需要修复的东西很少,起点和终点缺少一些小数位置。

Gist、dart pad 上的代码

class Slider3x extends StatefulWidget 
  const Slider3x(
    Key? key,
    required this.onSliderUpdate,
    this.size = const Size(5, 10),
    this.min = 0,
    this.max = 1.0,
    this.colorX = Colors.green,
    this.colorY = Colors.blue,
    this.colorZ = Colors.redAccent,
  ) : super(key: key);

  final Function(double? x, double? y, double? z) onSliderUpdate;

  ///size of moveable 3x point ?, forgot the name maybe thumbs
  final Size size;
  final double? min;
  final double? max;

  final Color colorX;
  final Color colorY;
  final Color colorZ;

  @override
  State<Slider3x> createState() => _Slider3xState();


class _Slider3xState extends State<Slider3x> 
  /// three slider position
  double? x;
  double? y;
  double? z;

  final double tapSpacesArea = .05;

  // currect active slider , help to prevent overlLAp while sliding
  int activeSliderNumber = 0;

  //* Update sldier
  void _updateSlider(double dx, double maxWidth) 
    final tapPosition = dx;

    //* update logic
    if (tapPosition <= 0 || tapPosition >= maxWidth) 
      return;
    

    //* update on UI based on slider number
    if (activeSliderNumber == 0) 
      setState(() 
        x = tapPosition;
      );
     else if (activeSliderNumber == 1) 
      setState(() 
        y = tapPosition;
      );
     else if (activeSliderNumber == 2) 
      setState(() 
        z = tapPosition;
      );
    

    //pass value on main widget
    widget.onSliderUpdate(
      dp(_generateSliderValue(maxWidth: maxWidth, x: x!)),
      dp(_generateSliderValue(maxWidth: maxWidth, x: y!)),
      dp(_generateSliderValue(maxWidth: maxWidth, x: z!)),
    );
  

  //round number
  double dp(double val, int places = 2) 
    num mod = pow(10.0, places);
    return ((val * mod).round().toDouble() / mod);
  

  //* calculate slider value
  double _generateSliderValue(
    required double maxWidth,
    required double x,
  ) 
    // x is slider original position on width:maxWidth

    return (widget.max! - widget.min!) * (x / maxWidth) + widget.min!;
  

  //* select ActiveSlider, fixed overLap issue
  //* slider Selector logic
  void _selectSlider(
    required double maxWidth,
    required double tapPosition,
  ) 
    final maxArea = maxWidth * tapSpacesArea;

    if ((tapPosition - x!).abs() < maxArea) 
      setState(() 
        activeSliderNumber = 0;
      );
     else if ((tapPosition - y!).abs() < maxArea) 
      setState(() 
        activeSliderNumber = 1;
      );
     else if ((tapPosition - z!).abs() < maxArea) 
      setState(() 
        activeSliderNumber = 2;
      );
    
  

  @override
  Widget build(BuildContext context) 
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          SizedBox(
            height: 50,
            child: LayoutBuilder(builder: (context, constraints) 
              final maxWidth = constraints.maxWidth - 10;
              x = x ?? 0;
              y = y ?? constraints.maxWidth / 2;
              z = z ?? maxWidth;
              return Stack(
                alignment: Alignment.center,
                children: [
                  Positioned(
                    left: x,
                    child: Container(
                      height: activeSliderNumber == 0
                          ? widget.size.height * 1.5
                          : widget.size.height,
                      width: widget.size.width,
                      color: widget.colorX,
                    ),
                  ),
                  //* paint Y
                  Positioned(
                    left: y,
                    child: Container(
                      height: activeSliderNumber == 1
                          ? widget.size.height * 1.5
                          : widget.size.height,
                      width: widget.size.width,
                      color: widget.colorY,
                    ),
                  ),
                  //* paint z
                  Positioned(
                    left: z,
                    child: Container(
                      height: activeSliderNumber == 2
                          ? widget.size.height * 1.5
                          : widget.size.height,
                      width: widget.size.width,
                      color: widget.colorZ,
                    ),
                  ),

                  const Divider(
                    endIndent: 10,
                  ),

                  GestureDetector(
                    onTapDown: (details) => _selectSlider(
                        maxWidth: maxWidth,
                        tapPosition: details.localPosition.dx),
                    onPanUpdate: (details) =>
                        _updateSlider(details.localPosition.dx, maxWidth),
                  ),
                ],
              );
            ),
          ),
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Text(
                widget.min.toString(),
              ),
              Text(
                widget.max.toString(),
              ),
            ],
          )
        ],
      ),
    );
  


【讨论】:

太棒了!奇迹般有效。非常感谢努力。谢谢

以上是关于如何在一个滑块上添加多个滑块? #扑的主要内容,如果未能解决你的问题,请参考以下文章

在jQuery滑块上添加刻度线? [重复]

在无限平滑修改的猫头鹰滑块上添加暂停

如何在滑块上创建这种效果?

到达一端时如何在点击滑块上制作无限过渡效果? (过渡问题)

flexslider 中的 GIF 滑块,如何仅在滑块上开始 gif

如何使 CAGradientLayer 中的渐变跟随滑块上的某个值?