如何在颤动中创建回叫

时间:2019-12-29 16:53:08

标签: flutter dart

我尝试在Flutter中构建自己的滑块。

但我遇到了问题。

如何创建类似flutter默认滑块onChanged的回调? 为了拥有我们自己的滑块,我们需要注册一个CallBack,但我不知道该怎么做?

这是我到目前为止的努力。

import 'dart:math';

import 'package:flutter/material.dart';

class WaveSlider extends StatefulWidget {
  final double value;
  final double barWidth;
  final int maxBarHight;
  final double width;
  final double min;
  final double max;
  final Color barColor;
  final Color barSideColor;
  final Color inActiveColor;

  WaveSlider({
    this.value = 0.0,
    this.barWidth = 5.0,
    this.maxBarHight = 50,
    this.width = 60.0,
    this.min = 0.0,
    this.max = 1.0,
    this.barColor = Colors.white,
    this.barSideColor = Colors.black,
    this.inActiveColor = Colors.grey,
  });
  @override
  State<StatefulWidget> createState() => WaveSliderState();
}

class WaveSliderState extends State<WaveSlider>
    with SingleTickerProviderStateMixin {
  AnimationController positionController;

  List<int> bars = [];
  double barPosition;
  double barWidth;
  int maxBarHight;
  double width;

  int numberOfBars;

  @override
  void initState() {
    super.initState();
    barPosition = widget.value;
    barWidth = widget.barWidth;
    maxBarHight = widget.maxBarHight.toInt();
    width = widget.width;
    if (bars.isNotEmpty) bars = [];
    numberOfBars = width ~/ barWidth;
    randomNumberGenerator();
  }

  void randomNumberGenerator() {
    Random r = Random();
    for (var i = 0; i < numberOfBars; i++) {
      bars.add(r.nextInt(maxBarHight - 10) + 10);
    }
  }

  _onTapDown(TapDownDetails details) {
    var x = details.globalPosition.dx;
    print("tapped " + (x).toString());
    // print(positionController.value);
    setState(() {
      barPosition = x;
    });
  }

  void _onHorizontalDragUpdate(DragUpdateDetails details) {
    setState(() {
      barPosition = details.globalPosition.dx;
    });
  }

  @override
  Widget build(BuildContext context) {
    int barItem = 0;
    return Center(
      child: GestureDetector(
        onTapDown: _onTapDown,
        onHorizontalDragUpdate: _onHorizontalDragUpdate,
        child: Container(
          child: Row(
            crossAxisAlignment: CrossAxisAlignment.end,
            mainAxisAlignment: MainAxisAlignment.center,
            children: bars.map((int height) {
              Color color = barItem + 1 < barPosition / barWidth
                  ? widget.barColor
                  : widget.inActiveColor;
              barItem++;
              return Row(
                children: <Widget>[
                  Container(
                    width: .1,
                    height: height.toDouble(),
                    color: widget.barSideColor,
                  ),
                  Container(
                    decoration: BoxDecoration(
                      color: color,
                      borderRadius: BorderRadius.only(
                        topLeft: const Radius.circular(1.0),
                        topRight: const Radius.circular(1.0),
                      ),
                    ),
                    height: height.toDouble(),
                    width: 4.8,
                  ),
                  Container(
                    width: .1,
                    height: height.toDouble(),
                    color: widget.barSideColor,
                  ),
                ],
              );
            }).toList(),
          ),
        ),
      ),
    );
  }
}

您可以像这样使用它:

WaveSlider(
          value: _animation.value,
          min: 0.0,
          max: 1.0,
          width: MediaQuery.of(context).size.width,
          barWidth: 5,
          maxBarHight: 50,
          barColor: Colors.black,
          barSideColor: Colors.white,
          inActiveColor: Colors.red,
        )

我查看了默认的颤动滑块,但对我来说非常执着。 非常感谢。

2 个答案:

答案 0 :(得分:1)

我添加了如下回调:

import 'dart:math';

import 'package:flutter/material.dart';

class WaveSlider extends StatefulWidget {
  final double value;
  final double barWidth;
  final int maxBarHight;
  final double width;
  final double min;
  final double max;
  final Color barColor;
  final Color barSideColor;
  final Color inActiveColor;
  final CalbackFunction callback;

  WaveSlider({
    this.value = 0.0,
    this.barWidth = 5.0,
    this.maxBarHight = 50,
    this.width = 60.0,
    this.min = 0.0,
    this.max = 1.0,
    this.barColor = Colors.white,
    this.barSideColor = Colors.black,
    this.inActiveColor = Colors.grey,
    this.callback,
  });
  @override
  State<StatefulWidget> createState() => WaveSliderState();
}

class WaveSliderState extends State<WaveSlider>
    with SingleTickerProviderStateMixin {
  AnimationController positionController;

  List<int> bars = [];
  double barPosition;
  double barWidth;
  int maxBarHight;
  double width;

  int numberOfBars;

  @override
  void initState() {
    super.initState();
    barPosition = widget.value;
    barWidth = widget.barWidth;
    maxBarHight = widget.maxBarHight.toInt();
    width = widget.width;
    if (bars.isNotEmpty) bars = [];
    numberOfBars = width ~/ barWidth;
    randomNumberGenerator();
  }

  void randomNumberGenerator() {
    Random r = Random();
    for (var i = 0; i < numberOfBars; i++) {
      bars.add(r.nextInt(maxBarHight - 10) + 10);
    }
  }

  _onTapDown(TapDownDetails details) {
    var x = details.globalPosition.dx;
    // print("tapped " + (x).toString());
    widget.callback(details.globalPosition); /// <-- I used callback here
    // print(positionController.value);
    setState(() {
      barPosition = x;
    });
  }

  void _onHorizontalDragUpdate(DragUpdateDetails details) {
    widget.callback(details.globalPosition); /// <-- I used callback here
    setState(() {
      barPosition = details.globalPosition.dx;
    });
  }

  @override
  Widget build(BuildContext context) {
    int barItem = 0;
    return Center(
      child: GestureDetector(
        onTapDown: _onTapDown,
        onHorizontalDragUpdate: _onHorizontalDragUpdate,
        child: Container(
          child: Row(
            crossAxisAlignment: CrossAxisAlignment.end,
            mainAxisAlignment: MainAxisAlignment.center,
            children: bars.map((int height) {
              Color color = barItem + 1 < barPosition / barWidth
                  ? widget.barColor
                  : widget.inActiveColor;
              barItem++;
              return Row(
                children: <Widget>[
                  Container(
                    width: .1,
                    height: height.toDouble(),
                    color: widget.barSideColor,
                  ),
                  Container(
                    decoration: BoxDecoration(
                      color: color,
                      borderRadius: BorderRadius.only(
                        topLeft: const Radius.circular(1.0),
                        topRight: const Radius.circular(1.0),
                      ),
                    ),
                    height: height.toDouble(),
                    width: 4.8,
                  ),
                  Container(
                    width: .1,
                    height: height.toDouble(),
                    color: widget.barSideColor,
                  ),
                ],
              );
            }).toList(),
          ),
        ),
      ),
    );
  }
}

typedef CalbackFunction = void Function(Offset value);

您可以按以下方式使用它:

WaveSlider(
            value: 0.0,
            min: 0.0,
            max: 1.0,
            width: MediaQuery.of(context).size.width,
            barWidth: 5,
            maxBarHight: 50,
            barColor: Colors.black,
            barSideColor: Colors.white,
            inActiveColor: Colors.red,
            callback: (offset) {
              print("callback " + (offset.dx).toString());
            },
          ))

希望它能对您有所帮助。

答案 1 :(得分:0)

wave_slider package的文档显示它具有用于回调的onChanged属性:

WaveSlider(
  onChanged: (double dragUpdate) {
    setState(() {
    _dragPercentage = dragUpdate *
        100; // dragUpdate is a fractional value between 0 and 1
    });
  },
)