Reputation: 273
I'm learning Flutter (and coding in general) and I can't seem to find the issue with my latest project. When I run in simulator the slider forms just fine, click the thumb and the label shows, but the thumb won't move on the track at all, and thus never calls the onChanged event.
import 'resources.dart';
import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
class ItemDetail extends StatefulWidget {
final Item item;
ItemDetail({Key key, @required this.item}) : super(key: key);
@override
_ItemDetailState createState() => new _ItemDetailState(item: item);
}
class _ItemDetailState extends State<ItemDetail> {
Item item;
_ItemDetailState({Key key, @required this.item});
@override
Widget build(BuildContext context) {
double margin = ((item.listPrice - item.stdUnitCost)/item.listPrice)*100;
return new Scaffold(
appBar: AppBar(
title: new Text('Item Detail'),
),
body: new Column(
children: <Widget>[
new Padding(padding: EdgeInsets.symmetric(vertical: 20.0)),
new Text(item.itemCode),
new Text(item.itemDescription),
new Text(item.itemExtendedDescription),
new Divider(height: 40.0,),
new Text('List Price: \$${item.listPrice}'),
new Text('Cost: \$${item.stdUnitCost}'),
item.itemType=='N'
? new Text('Non-Stock (${item.itemType})')
: new Text('Stock Item (${item.itemType})'),
new Text('Available: ${item.stockAvailable}'),
new Padding(padding: EdgeInsets.symmetric(vertical: 10.0)),
new Slider(
value: margin,
divisions: 20,
min: 0.0,
max: 100.0,
label: margin.round().toString(),
onChanged: (double value) {
setState(() {
margin = value;
});
},
)
],
),
);
}
}
Upvotes: 22
Views: 27213
Reputation: 1
In my case the problem was that the build tree was in a FutureBuilder, and the slider updates would get stuck at the async call. Moving the sliders to a widget under the FutureBuilder widget fixed the problem.
Upvotes: 0
Reputation: 60
My first problem was answered by Dinesh. Then the slider wasn't smooth. I was only able to tap to get it to move. I am on iOS, so I changed the Slider
widget to Slider.adaptive
.
This changes the slider to a CupertinoSlider
.
Copy and paste class for your testing convenience:
class MyStatefulWidget extends StatefulWidget {
const MyStatefulWidget({super.key});
@override
State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}
class _MyStatefulWidgetState extends State<MyStatefulWidget> {
double _currentSliderValue = 20;
@override
Widget build(BuildContext context) {
return Slider.adaptive(
value: _currentSliderValue,
max: 100,
divisions: 5,
label: _currentSliderValue.round().toString(),
onChanged: (double value) {
setState(() {
_currentSliderValue = value;
});
},
);
}
}
Upvotes: 0
Reputation: 374
This might help! (I USED STATEFULBUILDER TO UPDATE THE VALUE)
double _value = 20;
StatefulBuilder(
builder: (context, state) => Center(
child: CupertinoSlider(
value: _value,
min: 0.0,
max: 100.0,
onChanged: (val) {
state(() {
_value = val;
});
},
),
),
)
Upvotes: 8
Reputation: 10622
I got this issue when I put the variable inside the build function 😩
@override
Widget build(BuildContext context) {
int brightness = 85;
return Scaffold(
...
Moved the variable outside the function and got it solved 😎
int brightness = 85;
@override
Widget build(BuildContext context) {
return Scaffold(
...
because each time when state is changed, this build method is called and sets the variable back to the assigned value 😝
Upvotes: 17
Reputation: 1055
I was having an issue when giving the Slider(value: tasksDetails.taskImportance.toDouble(), etc)
I used Slider((_currentImportance ?? tasksDetails.taskImportance).toDouble(), etc)
and could then move the slider. I have no idea why this now works. Can only guess something to do with Denish's reason above 'Reason: Widgets will get rebuild only when there is a change in its state'. The selected slider value was in both cases was save correctly.
Upvotes: 0
Reputation: 11
I think the variable margin does not have scope from where the UI is building. When you debug, you can see changes in variable but it is not rendering. I tried it in following way and able to update the UI value.
class _MyHomePageState extends State<MyHomePage> {
double margin=0;
Widget getSlider(BuildContext context)
{
return Slider(
value:margin.toDouble(),
onChanged: (newRating){
setState(() {
margin = newRating;
});
},
min: 0,
max: 100,
divisions: 5,
);
} // getslider method closed
// @0verride Widget build method
// under children widgets , simply call the getSlider method to place the slider
} //class
Upvotes: 1
Reputation: 512566
For others coming here, I had a slightly different reason that the slider wasn't updating. I had the value
set to a constant. Make sure that value is a variable.
This:
Slider(
value: _myValue,
...
onChanged: (newValue) => {
setState(() => _myValue = newValue)
},
),
Not this:
Slider(
value: 0, // <-- problem
...
onChanged: (newValue) => {
setState(() => _myValue = newValue)
},
),
Upvotes: 20
Reputation: 21758
Problem: In the above example, margin
is not a state variable. It is a local variable inside a build
method.
Fix: Move this as an instance variable.
Reason: Widgets will get rebuild only when there is a change in its state.
Code:
class _ItemDetailState extends State<ItemDetail> {
Item item;
var margin;
_ItemDetailState({Key key, @required this.item}) {
this.margin = ((item.listPrice - item.stdUnitCost)/item.listPrice)*100;
}
@override
Widget build(BuildContext context) {
//same as now
}
}
Upvotes: 24