skip to Main Content

I am using Slider.adaptive in bottomsheet but it does not update my view regardless that I am using StatefulBuilder.

Here is minimized version of my code:

Duration _duration = const Duration(milliseconds: 0);
Duration _position = const Duration(milliseconds: 0);

@override
Widget build(BuildContext context) {
  return PopScope(
    canPop: false,
    onPopInvoked: (bool didPop) async {
      if (isPlaying == true) {
        setState(() async {
          await audioPlayer.stop();
        });
      }
    },
    child: Scaffold(
      body: SafeArea(
        child: Center(
          child: Text('Testing Screen'),
        )
      ),
      bottomNavigationBar: BottomAppBar(
        padding: EdgeInsets.zero,
        color: Colors.black,
        height: 130,
        child: Column(
          children: [
            IconButton(
              icon: const FaIcon(
                FontAwesomeIcons.headphones,
                color: Colors.white70,
              ),
              onPressed: () async {
                _openAudioBottomSheet();
              },
            ),
          ]
        ),
      ),
    ),
  );
}

void  _openAudioBottomSheet() {
  showModalBottomSheet(
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(20.0)),
      ),
      context: context,
      showDragHandle: true,
      builder: (BuildContext context) {
        return StatefulBuilder(
          builder: (BuildContext context, StateSetter setState) {
            return SingleChildScrollView(
              child: Padding(
                padding: const EdgeInsets.all(20),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisAlignment: MainAxisAlignment.start,
                  children: [
                    Slider.adaptive(
                      min: 0,
                      max: _duration.inSeconds.toDouble(),
                      value: _position.inSeconds.toDouble(),
                      onChanged: (value) async {
                        debugPrint('value is:: $value');
                        setState(() {
                          _position = Duration(seconds: value.toInt());
                        });
                      },
                    ),
                  ],
                ),
              ),
            );
          }
        );
      }
  );
}

Any idea of how to make this view update works?

Update

I’ve noticed one thing just now, problem is most likely caused by _position data not passing to showModalBottomSheet rather than onChanged method issue!

It seems _position will not get updated duration in bottom sheet therefore slider doesn’t move forward.

here is my audioplayer initialization code:

@override
  void initState() {
    super.initState();
    initAudioPlayer();
  }

  initAudioPlayer() async {
    audioPlayer.setAudioContext(
        const AudioContext(
          android: AudioContextAndroid(),
          iOS: AudioContextIOS(),
        )
    );

    audioPlayer.onPlayerStateChanged.listen((PlayerState event) {
      setState(() {
        isPlaying = event == PlayerState.playing;
        audioPlayer.setVolume(_volume);

        if (PlayerState == PlayerState.completed || PlayerState == PlayerState.stopped || PlayerState == PlayerState.paused) {
          setState(() {
            isLoading = false; // Loading is complete
          });
        } else if (PlayerState == PlayerState.playing) {
          setState(() {
            isLoading = true; // Audio loading is in progress
          });
        }
      });
    });

    audioPlayer.onDurationChanged.listen((Duration event) {
      setState(() {
        _duration = event;
      });
    });

    audioPlayer.onPositionChanged.listen((Duration event) {
      // this does get updated, but wont pass to bottomsheet!
      debugPrint('value is: $event');
      setState(() {
        _position = event;
      });
    });
  }

3

Answers


  1. The reason it is not updating because the max and min are same which is zero.

    Another noticeable thing is, you have define millisecond on but using as second, have the same format will make it more readable.


      Duration _duration = const Duration(seconds: 1000);
      Duration _position = const Duration(seconds: 0);
      void _openAudioBottomSheet() async {
        await showModalBottomSheet(
          context: context,
          builder: (BuildContext context) {
            return StatefulBuilder(
              builder: (BuildContext context, StateSetter setStateSB) {
                return SingleChildScrollView(
                  child: Padding(
                    padding: const EdgeInsets.all(20),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      mainAxisAlignment: MainAxisAlignment.start,
                      children: [
                        Slider.adaptive(
                          min: 0,
                          max: _duration.inSeconds.toDouble(),
                          value: _position.inSeconds.toDouble(),
                          onChanged: (value) async {
                            debugPrint('value is:: $value');
                            setStateSB(() {
                              _position = Duration(seconds: value.toInt());
                            });
                          },
                        ),
                      ],
                    ),
                  ),
                );
              },
            );
          },
        );
      }
    
    Login or Signup to reply.
  2. using this one changed to Statefull Builder position and showBottomSheet instead of showModelBottomSheet

    void  _openAudioBottomSheet() {
      showBottomSheet(
          shape: const RoundedRectangleBorder(
            borderRadius: BorderRadius.vertical(top: Radius.circular(20.0)),
          ),
          context: context,
          builder: (BuildContext context) {
            return SingleChildScrollView(
              child: Padding(
                padding: const EdgeInsets.all(20),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisAlignment: MainAxisAlignment.start,
                  children: [
                    StatefulBuilder(
                      builder: (context, setState) {
                        return Slider.adaptive(
                          min: 0,
                          max: _duration.inSeconds.toDouble(),
                          value: _position.inSeconds.toDouble(),
                          onChanged: (value) async {
                            debugPrint('value is:: $value');
                            setState(() {
                              _position = Duration(seconds: value.toInt());
                            });
                          },
                        );
                      }
                    )
                  ]
                )
              )
            );
          }
      );
    }
    
    Login or Signup to reply.
  3. You are using an audio player library, and you’ve correctly identified that the issue might be related to _position not getting updated in the showModalBottomSheet. This could be due to the fact that the showModalBottomSheet creates a separate context for the bottom sheet, and the state might not be properly passed.

    By passing _position as a parameter to _openAudioBottomSheet and using it as the initial value for the slider, you ensure that the correct position is set in the bottom sheet.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search