如何在flutter中创建这个滑块来控制音量?

问题描述 投票:0回答:1

image

我需要使滑块上的舍入小于默认值。怎么做?我没有找到答案。我使用的是 Flutter Null 安全版本。非常感谢。 我尝试更多使用容器、带有滑块的进度条等。

flutter slider
1个回答
0
投票

final class VolumeControlWidget extends StatefulWidget {
  const VolumeControlWidget({super.key});

  @override
  State<VolumeControlWidget> createState() => _VolumeControlWidgetState();
}

class _VolumeControlWidgetState extends State<VolumeControlWidget> {
  final double maxVolume = kMinInteractiveDimension * 5;
  final double minVolume = kMinInteractiveDimension * .5;
  double currentVolume = 0;
  final double borderThickness = 1.5;

  void setVolume(double volume) {
    setState(() {
      currentVolume = volume.clamp(minVolume, maxVolume).roundToDouble();
    });
  }

  @override
  void initState() {
    currentVolume = minVolume;
    super.initState();
  }

  bool get isMax => currentVolume == maxVolume;

  bool get isMin => currentVolume <= minVolume;

  int get volumePercentage => ((currentVolume / maxVolume) * 100).round().clamp(0, 100);

  @override
  Widget build(BuildContext context) {
    return Container(
      height: maxVolume,
      width: kMinInteractiveDimension * 1.2,
      constraints: BoxConstraints(minHeight: minVolume, maxHeight: maxVolume),
      decoration: ShapeDecoration(
        shape: StadiumBorder(
          side: BorderSide(
            width: borderThickness,
            color: Colors.deepPurpleAccent.shade700,
          ),
        ),
      ),
      clipBehavior: Clip.antiAlias,
      child: RawGestureDetector(
        gestures: {
          VerticalDragGestureRecognizer: GestureRecognizerFactoryWithHandlers<VerticalDragGestureRecognizer>(
            VerticalDragGestureRecognizer.new,
            (VerticalDragGestureRecognizer instance) {
              instance.onUpdate = (DragUpdateDetails details) {
                final double newVolume = currentVolume - details.delta.dy;
                setVolume(newVolume);
              };
            },
          ),
        },
        child: Column(
          mainAxisAlignment: MainAxisAlignment.end,
          children: [
            AnimatedContainer(
              duration: const Duration(milliseconds: 50),
              constraints: BoxConstraints(minHeight: minVolume, maxHeight: maxVolume),

              ///
              /// (borderThickness * 2) because , we have border on top and bottom
              ///
              ///
              height: currentVolume - (borderThickness * 2),
              width: isMin ? kMinInteractiveDimension : kMinInteractiveDimension * 1.2,
              decoration: BoxDecoration(
                borderRadius: const BorderRadius.vertical(
                  top: Radius.circular(200),
                ),
                gradient: LinearGradient(
                  colors: [
                    Colors.deepPurpleAccent.shade200,
                    Colors.deepPurpleAccent.shade400,
                    Colors.deepPurpleAccent.shade700,
                  ],
                  begin: AlignmentDirectional.bottomCenter,
                  end: AlignmentDirectional.topCenter,
                ),
              ),
              child: isMin
                  ? Align(
                      alignment: isMin
                          ? const AlignmentDirectional(
                              0,
                              0.2,
                            )
                          : Alignment.center,
                      child: Container(
                        width: kMinInteractiveDimension * .5,
                        height: isMin ? 1 : borderThickness,
                        decoration: BoxDecoration(
                          color: Colors.white,
                          borderRadius: BorderRadius.circular(2),
                        ),
                      ),
                    )
                  :

                  ///
                  /// Optional : You can use only Sizedbox() instead of this
                  ///
                  SizedBox(
                      child: Center(
                        child: Text(
                          '% ${volumePercentage.toStringAsFixed(1)}',
                          style: const TextStyle(color: Colors.white),
                        ),
                      ),
                    ),
            ),
          ],
        ),
      ),
    );
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.