In this example I have 3 sliders, dragging one slider should update the secondary track of all the sliders
This however does not work when the sliders are wrapped with a ListView, notice how the top two tracks do not update until I mouse over them:
Changing the ListView to a Column yeilds the desired behaviour:
Any idea how I can benefit from the virtualisation of ListView and get the on-screen items to update?
class ShareData with ChangeNotifier {
double share;
double shareAvailable;
ShareData({required this.share, required this.shareAvailable});
void setShareAvaialble(double value) {
shareAvailable = value;
notifyListeners();
}
}
class ShareSlider extends StatefulWidget {
const ShareSlider({super.key});
@override
State<ShareSlider> createState() => _ShareSliderState();
}
class _ShareSliderState extends State<ShareSlider> {
late List<ShareData> _shares;
@override
void initState() {
_shares = List<ShareData>.generate(3, (index) => ShareData(share: 1.0 / 3, shareAvailable: 1.0 / 3));
super.initState();
}
@override
Widget build(BuildContext context) {
return ListView( //<---- Change me to Column
children: _shares
.map(
(s) => ListenableBuilder(
listenable: s,
builder: (c, o) => Slider(
value: s.share,
secondaryTrackValue: s.shareAvailable,
onChanged: (e) {
s.share = e;
for (int i = 0; i < _shares.length; ++i) {
_shares[i].setShareAvaialble(1 - e);
}
}),
),
)
.toList());
}
}
Expecting all 3 bars to update
2
Answers
Fixed it, in a slightly hacky way
Using UniqueKey correctly re-renders everything on updates. However this has the side-effect of re-creating the widget the user is currently interacting - breaking dragging.
So instead I use a ValueKey for each widget and only update the keys of the siders we are not interacting with:
You’re changing State without calling setState. Fix that first.
My theory:
It works when it’s a column, because the slider updates, causing the column it’s in to update as well.
It fails in a ListView because the items of a ListView are separately considered, and so the item holding the slider is refreshed, but the neighbors aren’t.