在我的应用程序中,我有一个PageView
和一个Slider
。当我滚动PageView
时,我预计Slider
会更改其值,当我滑动Slider
时,我希望PageView
的页面也会更改。为此,我有一个状态,即Slider
的value
,在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();
});
},
)
问题是,我现在有两个地方可以更改_sliderValue
——一个在onChanged
中,Slider
可以响应,一个在onPageChanged
中,可以滚动。当我反复按下滑块时,它会发出刺耳的声音。
有什么办法解决这个问题吗?
实际上,这种情况下的问题在于,对于每一次页面更改,都会触发PageView
的onPageChanged
回调。例如,如果我们在第1页,并使用Slider
移动到第5页,则onPageChanged
将被调用4次(对于第2-3-4-5页(,因此Slider
的值状态将重复更改4次。这导致Slider
的砰砰声在各处跳跃。
我试图通过在onPageChanged
中设置Timer
来修复它,以便在触发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
必须等待300ms才能更新其值(,但这是一个改进。如果有人有更好的解决方案,我很高兴听到。
请使用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()),