You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter滑块SharedPreferences保存值UI不显示问题求助

问题分析与解决方案

你的滑块UI始终显示1.0,核心问题是音量单位不匹配加上初始化顺序错误:

问题根源

  1. FlutterVolumeController的音量值范围是0.0~1.0(代表0%~100%的比例),但你的Slider用的是0.0~100.0的范围,两者单位不兼容。
  2. initState中你先从SharedPreferences加载值,随后添加的音量监听器会立即触发,用系统当前音量的0~1值覆盖掉你从SP加载的0~100值,导致滑块显示1.0(对应系统最大音量的1.0)。
  3. 调用FlutterVolumeController.setVolume时传入0~100的数值,会被插件截断为1.0,直接把系统音量拉满。

修复步骤

  1. 统一数值转换:在FlutterVolumeController和Slider之间做数值转换,把插件的0~1比例转成0~100的百分比。
  2. 调整初始化顺序:先加载SP值,再用该值设置系统音量,最后添加监听器,避免监听器覆盖初始值。
  3. 移除冗余操作:删除initState中加载SP后立即存回的多余代码。
  4. 确认SP默认值:确保SharedPreferencesService.getDouble在无保存值时返回0.0或合理默认值(比如50.0)。

修改后的完整代码

class AppSettings extends StatefulWidget {
  const AppSettings({super.key});

  @override
  State<AppSettings> createState() => _AppSettingsState();
}

class _AppSettingsState extends State<AppSettings> {
  double sliderValue = 0;
  final double _minValue = 0.0;
  final double _maxValue = 100.0;
  bool isSelected = false;
  final GlobalKey _sliderKey = GlobalKey();

  void toggleSwitch(bool value) {
    setState(() {
      isSelected = !isSelected;
    });
  }

  @override
  void initState() {
    super.initState();
    FlutterVolumeController.updateShowSystemUI(false);
    // 先加载保存的音量值
    SharedPreferencesService().getDouble("slider_value").then((savedValue) {
      setState(() {
        sliderValue = savedValue;
        debugPrint("Loaded saved value: $sliderValue");
        // 用保存的值设置系统音量(转成0~1的比例)
        FlutterVolumeController.setVolume(sliderValue / 100);
      });
      // 加载完成后再添加监听器,避免覆盖初始值
      FlutterVolumeController.addListener((volume) {
        setState(() {
          // 把系统返回的0~1比例转成0~100的百分比
          sliderValue = volume * 100;
          SharedPreferencesService().setDouble("slider_value", sliderValue);
        });
      });
    });
  }

  void _incrementSlider() {
    setState(() {
      if (sliderValue < _maxValue) {
        sliderValue = (sliderValue + 10).clamp(_minValue, _maxValue);
        // 转成0~1的比例设置系统音量
        FlutterVolumeController.setVolume(sliderValue / 100);
        SharedPreferencesService().setDouble("slider_value", sliderValue);
      }
    });
  }

  void _decrementSlider() {
    setState(() {
      if (sliderValue > _minValue) {
        sliderValue = (sliderValue - 10).clamp(_minValue, _maxValue);
        FlutterVolumeController.setVolume(sliderValue / 100);
        SharedPreferencesService().setDouble("slider_value", sliderValue);
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    debugPrint("Current slider value: $sliderValue");
    return Scaffold(
      resizeToAvoidBottomInset: false,
      appBar: AppBar(
        elevation: 0.5,
        shadowColor: Colors.white,
        title: const Row(
          children: [
            SizedBox(width: 10.0),
            Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(
                  "App Settings",
                  style: TextStyle(fontSize: 22.0, fontWeight: FontWeight.bold),
                )
              ],
            )
          ],
        ),
      ),
      body: SafeArea(
        child: Padding(
          padding: const EdgeInsets.only(left: 20.0, right: 12.0, top: 12.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const Padding(
                padding: EdgeInsets.only(bottom: 8.0),
                child: Text("Volume", style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),),
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.start,
                children: [
                  InkWell(
                    onTap: _decrementSlider,
                    child: Container(
                      width: 36,
                      height: 36,
                      decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(6),
                          color: Colors.white,
                          border: Border.all(color: Colors.black, width: 2)
                      ),
                      child: const Icon(Icons.remove),
                    ),
                  ),
                  Expanded(
                    child: Slider(
                      key: _sliderKey,
                      value: sliderValue,
                      min: _minValue,
                      max: _maxValue,
                      thumbColor: Colors.black,
                      activeColor: Colors.black,
                      inactiveColor: AppColors.colorDarkGrey,
                      onChanged: (newValue) {
                        setState(() {
                          sliderValue = newValue;
                          FlutterVolumeController.setVolume(newValue / 100);
                          SharedPreferencesService().setDouble("slider_value", sliderValue);
                        });
                      },
                    ),
                  ),
                  InkWell(
                    onTap: _incrementSlider,
                    child: Container(
                      width: 36,
                      height: 36,
                      decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(6),
                          color: Colors.black,
                          border: Border.all(color: Colors.black, width: 2)
                      ),
                      child: const Icon(Icons.add, color: Colors.white,),
                    ),
                  ),
                ],
              ),
              const Padding(
                padding: EdgeInsets.only(top: 14.0, bottom: 18),
                child: Text("", style: TextStyle(fontSize: 18),),
              ),
              Row(
                children: [
                  const Text("", style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),),
                  const Spacer(),
                  Switch(
                    value: isSelected,
                    onChanged: toggleSwitch,
                    activeColor: Colors.white,
                    inactiveThumbColor: Colors.black,
                    activeTrackColor: Colors.black,
                  )
                ],
              )
            ],
          ),
        ),
      ),
    );
  }
}

额外注意

  • 检查SharedPreferencesService.getDouble的实现,确保当slider_value不存在时返回0.0(或你期望的默认音量,比如50.0),避免初始值异常。
  • 如果你的FlutterVolumeController版本有其他参数或行为差异,可根据插件文档微调转换逻辑。

内容的提问来源于stack exchange,提问作者varrun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 08:05:13