Flutter 中的负向正向滑块

Jae*_*ebi 5 slider seekbar dart dart-pub flutter

我正在尝试实现一个温度滑块,它可以从负值变为正值。

我发现了许多滑块从左到右的示例,但我还没有找到从中间开始向左(负)和右(正)的滑块。

附图显示了我想要实现的目标。是否有一个小部件或库(我不确定它是否称为 Slider)可以实现所需的小部件?

在此输入图像描述

Dec*_*oth 6

简单的答案

\n

也许FlutterSlider提供的 Widget可以实现您所希望的良好行为。

\n

有了这个小部件,您可以

\n
    \n
  1. 定义最小值 = -50
  2. \n
  3. 定义最大值 = 50
  4. \n
  5. 将起点设置为 0
  6. \n
  7. 自定义栏的颜色。
  8. \n
\n

我为您编写了一个简单但完整的示例,它可能为您提供一个良好的起点:

\n
import \'package:flutter/material.dart\';\n\nvoid main() {\n  runApp(const MyApp());\n}\n\nclass MyApp extends StatelessWidget {\n  const MyApp({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      title: \'Flutter Demo\',\n      theme: ThemeData(\n        primarySwatch: Colors.blue,\n      ),\n      home: const MyHomePage(title: \'Flutter Demo Home Page\'),\n    );\n  }\n}\n\nclass MyHomePage extends StatefulWidget {\n  const MyHomePage({super.key, required this.title});\n\n  final String title;\n\n  @override\n  State<MyHomePage> createState() => _MyHomePageState();\n}\n\nclass _MyHomePageState extends State<MyHomePage> {\n  void _restartSlider() {\n    setState(() {\n      _sliderValue=0;\n    });\n  }\n\n  double _sliderValue = 0;\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(\n        title: Text(widget.title),\n      ),\n      body: Center(\n        child: Column(\n          mainAxisAlignment: MainAxisAlignment.spaceEvenly,\n          children: [\n            Text("Slider value is: $_sliderValue",),\n            Slider(\n              value: _sliderValue,\n              activeColor: Colors.red,\n              inactiveColor: Colors.green,\n              thumbColor: _sliderValue == 0 ? Colors.grey : _sliderValue > 0 ? Colors.green : Colors.red,\n              min: -50, max: 50,\n              divisions: 100,\n              label: _sliderValue.toString(),\n              onChanged: (double newValue) {\n                setState(() {\n                  _sliderValue = newValue;\n                });\n              },\n            ),\n          ],\n        ),\n      ),\n      floatingActionButton: FloatingActionButton(\n        onPressed: _restartSlider,\n        tooltip: \'Restart\',\n        child: const Icon(Icons.restart_alt),\n      ),\n    );\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

该代码将创建一个滑块“从中间开始,向左(负)和向右(正) ”。结果是这样的(点击浮动按钮使滑块返回0):

\n

在此输入图像描述

\n

详细的答案

\n

使用Stack小部件,您可以绘制一个与图片中显示的完全相同的条形。

\n

基本上,您只需将Slider\ 的条形颜色设置为透明,并在下面绘制一个具有您想要的颜色的容器。\n完整的工作示例如下:

\n
import \'package:flutter/material.dart\';\n\nvoid main() {\n  runApp(const MyApp());\n}\n\nclass MyApp extends StatelessWidget {\n  const MyApp({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      title: \'Flutter Demo\',\n      theme: ThemeData(\n        primarySwatch: Colors.blue,\n      ),\n      home: const MyHomePage(title: \'Flutter Demo Home Page\'),\n    );\n  }\n}\n\nclass MyHomePage extends StatefulWidget {\n  const MyHomePage({super.key, required this.title});\n\n  final String title;\n\n  @override\n  State<MyHomePage> createState() => _MyHomePageState();\n}\n\nclass _MyHomePageState extends State<MyHomePage> {\n  void _restartSlider() {\n    setState(() {\n      _sliderValue=0;\n    });\n  }\n\n  double _sliderValue = 0;\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(\n        title: Text(widget.title),\n      ),\n      body: Center(\n        child: Column(\n          mainAxisAlignment: MainAxisAlignment.spaceEvenly,\n          children: [\n            Text("Temperature is: $_sliderValue \xc2\xb0C",),\n            Stack(alignment: AlignmentDirectional.center,\n\n              children: [\n                Padding(\n                  padding: const EdgeInsets.all(16.0),\n                  child: Row(\n                    children: [\n                      Expanded(\n                        child: Container(\n                          height: 7,\n                          color: _sliderValue < 0 ? Colors.red : Colors.grey,\n                        ),\n                      ),\n                      Expanded(\n                        child: Container(\n                          height: 7,\n                          color: _sliderValue > 0 ? Colors.green : Colors.grey,\n                        ),\n                      ),\n                    ],\n                  ),\n                ),\n                Slider(\n                  value: _sliderValue,\n                  activeColor: Colors.transparent,\n                  inactiveColor: Colors.transparent,\n                  thumbColor: _sliderValue == 0 ? Colors.grey : _sliderValue > 0 ? Colors.green : Colors.red,\n                  min: -50, max: 50,\n                  divisions: 100,\n                  label: _sliderValue.toString(),\n                  onChanged: (double newValue) {\n                    setState(() {\n                      _sliderValue = newValue;\n                    });\n                  },\n                ),\n              ],\n            ),\n          ],\n        ),\n      ),\n      floatingActionButton: FloatingActionButton(\n        onPressed: _restartSlider,\n        tooltip: \'Restart\',\n        child: const Icon(Icons.restart_alt),\n      ),\n    );\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

这将产生如下图所示的滑块:

\n
    \n
  1. 外壳温度为 0:

    \n

    在此输入图像描述

    \n
  2. \n
  3. 外壳温度为-50 \xc2\xb0C:

    \n

    在此输入图像描述

    \n
  4. \n
  5. 外壳温度为 50 \xc2\xb0C:

    \n

    在此输入图像描述

    \n
  6. \n
\n

如果只有滑块的那部分直到拇指应该着色,您可以使用LinearProcessIndicator来动态地仅对条形的一部分进行着色。这是按下面的代码完成的:

\n
import \'package:flutter/material.dart\';\n\nvoid main() {\n  runApp(const MyApp());\n}\n\nclass MyApp extends StatelessWidget {\n  const MyApp({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      title: \'Flutter Demo\',\n      theme: ThemeData(\n        primarySwatch: Colors.blue,\n      ),\n      home: const MyHomePage(title: \'Flutter Demo Home Page\'),\n    );\n  }\n}\n\nclass MyHomePage extends StatefulWidget {\n  const MyHomePage({super.key, required this.title});\n\n  final String title;\n\n  @override\n  State<MyHomePage> createState() => _MyHomePageState();\n}\n\nclass _MyHomePageState extends State<MyHomePage> {\n  void _restartSlider() {\n    setState(() {\n      _sliderValue=0;\n    });\n  }\n\n  double _sliderValue = 0;\n\n  double _min = -60;\n  double _max = 80;\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(\n        title: Text(widget.title),\n      ),\n      body: Center(\n        child: Column(\n          mainAxisAlignment: MainAxisAlignment.spaceEvenly,\n          children: [\n            Text("Temperature is: $_sliderValue \xc2\xb0C",),\n            Stack(alignment: AlignmentDirectional.center,\n              children: [\n                Padding(\n                  padding: const EdgeInsets.all(16.0),\n                  child: Row(\n                    children: [\n                      Expanded(\n                        child: LinearProgressIndicator(\n                          value: 1-_sliderValue/_min,\n                          color: Colors.grey,\n                          backgroundColor: Colors.red,\n                        ),\n                        flex:_min.abs().round(),\n                      ),\n                      Expanded(\n                        child: LinearProgressIndicator(\n                          value: _sliderValue/_max,\n                          color: Colors.green,\n                          backgroundColor: Colors.grey,\n                        ),\n                        flex:_max.abs().round(),\n                      ),\n                    ],\n                  ),\n                ),\n                Slider(\n                  value: _sliderValue,\n                  activeColor: Colors.transparent,\n                  inactiveColor: Colors.transparent,\n                  thumbColor: _sliderValue == 0 ? Colors.grey : _sliderValue > 0 ? Colors.green : Colors.red,\n                  min: _min, max: _max,\n                  divisions: (_min.abs() + _max.abs()).round(),\n                  label: _sliderValue.toString(),\n                  onChanged: (double newValue) {\n                    setState(() {\n                      _sliderValue = newValue;\n                    });\n                  },\n                ),\n              ],\n            ),\n          ],\n        ),\n      ),\n      floatingActionButton: FloatingActionButton(\n        onPressed: _restartSlider,\n        tooltip: \'Restart\',\n        child: const Icon(Icons.restart_alt),\n      ),\n    );\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n

给出以下结果:

\n

在此输入图像描述

\n


小智 1

您可以使用 RangeSlider 小部件。

以下是范围滑块的示例代码。如果需要保持中心点不变,可以使用onChanged回调方法使中心值不变。

class MyStatefulWidget extends StatefulWidget {
  const MyStatefulWidget({Key? key}) : super(key: key);

  @override
  State<MyStatefulWidget> createState() => _MyStatefulWidgetState();
}

class _MyStatefulWidgetState extends State<MyStatefulWidget> {
  RangeValues _currentRangeValues = const RangeValues(0, 0);

  @override
  Widget build(BuildContext context) {
    return RangeSlider(
      values: _currentRangeValues,
      max: 100,
      min: -100,
      divisions: 150,
      labels: RangeLabels(
        _currentRangeValues.start.round().toString(),
        _currentRangeValues.end.round().toString(),
      ),
      onChanged: (RangeValues values) {
        setState(() {
          _currentRangeValues = values;
        });
      },
    );
  }
}
Run Code Online (Sandbox Code Playgroud)