themene
themene

Reputation: 273

Flutter Slider Not Moving or Updating

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

Answers (8)

Chad Smith
Chad Smith

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

domtom
domtom

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

Mr. Poopybutthole
Mr. Poopybutthole

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

Abdul Saleem
Abdul Saleem

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

Sctajc
Sctajc

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

Vishnu V
Vishnu V

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

Suragch
Suragch

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

Dinesh Balasubramanian
Dinesh Balasubramanian

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

Related Questions