2

在我的应用程序中,我有一个PageView和一个Slider. 当我滚动 时PageView,我希望Slider改变它的值,当我滑动时,Slider我希望页面PageView也会改变。为此,我有一个状态是valueSlider,并且在onChanged我将改变它的值,并且onChangeEnd将动画PageView到期望的位置:

Slider(
   value: _sliderValue,
   onChanged: (val) {
      setState(() {
         _sliderValue = val;
      });
   },
   onChangeEnd: (val) {
      _controller.animateToPage(val.toInt(),
          duration: Duration(milliseconds: 300), curve: Curves.ease);
      },
   max: (pages.length - 1).toDouble())

在 中PageView,我也必须更新_sliderValue,所以当我滚动时它可以工作PageView

PageView.builder(
  onPageChanged: (page) {
    setState(() {
       _sliderValue = page.toDouble();
    });
  },
)

问题是,我现在有 2 个地方需要更改_sliderValue- 一个onChanged用于Slider响应,一个onPageChanged用于滚动。当我反复按下滑块时,这会使滑块震动。

有没有办法解决这个问题?

4

2 回答 2

1

实际上,这种情况的问题在于,每改变一次页面,都会触发的onPageChanged回调。PageView例如,如果我们在第 1 页并使用Slider移动到第 5 页,那么onPageChanged将被调用 4 次(对于第 2-3-4-5 页),结果 的值状态Slider将重复更改 4 次. 这会导致砰砰的声音在Slider各处跳跃。

我试图通过让Timer内部onPageChanged在触发之前等待一段时间来修复它setState,因此它仅在最后一次页面更改完成后才会触发。

// Define a Timer object in your state
Timer _timer;
PageView.builder(
  onPageChanged: (page) {
    // If there is a Timer running, cancel it
    if (_timer != null) {
      _timer.cancel();
    }
    // Setup a new Timer
    _timer = Timer(Duration(milliseconds: 300), () {
      setState(() {
        _sliderValue = page.toDouble();
      });
    });
  },
)

这可能看起来很老套,结果实际上并不完美(当您手动滚动页面时,Slider必须等待 300 毫秒才能更新其值),但它仍然是一个改进。如果有人有更好的解决方案,我很高兴听到。

于 2020-03-05T00:51:44.453 回答
0

请使用 val.round() 而不是 val.toInt()。

            Slider(
            value: _sliderValue,
            onChanged: (val) {
              setState(() {
                _sliderValue = val.round().toDouble(); // this line changed.
              });
            },
            onChangeEnd: (val) {
              _controller.animateToPage(val.round(), // this line changed.
                  duration: Duration(milliseconds: 300), curve: Curves.ease);
            },
            max: (pages.length - 1).toDouble()),
于 2020-03-04T10:20:04.763 回答