我们都熟悉家用开关来打开和关闭我们的照明系统和其他电器。 我们也熟悉切换按钮; 如果您家里有电炊具或电磁炉,您可以在其电压和烹饪功能之间切换。

同样,我们的移动应用程序也有开关和拨动开关来打开/关闭 Wi-Fi、蓝牙等。

今天,我们正在深入了解 Flutter 开关和切换的参数和属性。

目录

  • 什么是开关小部件?

  • 什么是切换小部件?

  • 开关和拨动之间的关键区别

  • 切换小部件示例

    • 安卓

    • iOS

    • 带图片的安卓开关

  • 切换小部件示例

    • 单个和必需的拨动开关

    • 单个且不需要的拨动开关

    • 需要多选

    • 不需要的多项选择

  • 创建自定义动画开关按钮

  • 用于开关和切换的流行 Flutter 包

什么是开关小部件?

开关按钮是一个 Flutter 小部件,只有两种状态,真/假或开/关。 通常,开关是一个带有拇指滑块的按钮,用户可以将其从左拖动到右,反之亦然以在状态之间切换。 它不会自行维护其状态。 您必须致电 onChanged属性以保持按钮打开或关闭。

什么是切换小部件?

同样,切换小部件只有两种状态:真/假或开/关。 但是切换小部件会创建多个按行排列的按钮,允许用户在它们之间切换。

开关和拨动之间的关键区别

这是移动应用程序中的用例问题。 在大多数情况下,这些小部件用于设置页面。 如果您向下拖动移动应用程序的通知面板,您将看到一个切换按钮网格。 但是当您进入设置页面时,这些按钮将更改为开关。

你一定明白其中的区别。 在您的移动应用程序中,如果您有一个只需要两种状态的控件列表,您应该使用开关。 如果一行或网格中有多个控件,则应使用切换。

切换小部件示例

Flutter 提供了三种类型的 switch 小部件:


超过 20 万开发人员使用 LogRocket 来创造更好的数字体验 了解更多 →


  • 开关(安卓)

  • CupertinoSwitch (iOS)

  • Switch.adaptive(根据平台适配)

让我们看一下用于自定义小部件的最常用属性:

Switch(安卓)

Switch(// thumb color (round icon)activeColor: Colors.amber,activeTrackColor: Colors.cyan,inactiveThumbColor: Colors.blueGrey.shade600,inactiveTrackColor: Colors.grey.shade400,splashRadius: 50.0,// boolean variable valuevalue: forAndroid,// changes the state of the switchonChanged: (value) => setState(() => forAndroid = value),
),

CupertinoSwitch(iOS)

CupertinoSwitch(// overrides the default green color of the trackactiveColor: Colors.pink.shade200,// color of the round icon, which moves from right to leftthumbColor: Colors.green.shade900,// when the switch is offtrackColor: Colors.black12,// boolean variable valuevalue: forIos,// changes the state of the switchonChanged: (value) => setState(() => forIos = value),
),

自适应开关小部件没有任何独特或不同的属性。 但是安卓 Switch如果您想要图像或图标而不是通常的拇指颜色,可以进一步自定义小部件。 您需要使用资产图像定义拇指图像属性。 请看下面的代码。

安卓 Switch带图像

Switch(trackColor: MaterialStateProperty.all(Colors.black38),activeColor: Colors.green.withOpacity(0.4),inactiveThumbColor: Colors.red.withOpacity(0.4),
// when the switch is on, this image will be displayedactiveThumbImage: const AssetImage('assets/happy_emoji.png'),
// when the switch is off, this image will be displayedinactiveThumbImage: const AssetImage('assets/sad_emoji.png'),value: forImage,onChanged: (value) => setState(() => forImage = value),
),

这就是代码在运行中的样子:

目前,我们不保存开关小部件的状态; 我们只是在改变它。 接下来是创建一个小应用程序,我们将在其中将主题从浅色更改为深色,反之亦然,当您关闭应用程序时,它的状态将被保存。

它是一个简单的单页应用程序,在 appBar,这将改变主题。

我已经使用 Flutter Hive 来保存应用程序的状态。 您可以使用 SharedPreferences,但我选择了 Hive,因为它是一个快速、轻量级的 NoSQL 数据库,适用于 Flutter 和 Dart 应用程序。 如果您需要一个没有大量关系的简单键值数据库,Hive 会很有帮助。 它使用起来毫不费力,并且是一个离线数据库(在本地存储数据)。

我们先来看代码……

我们正在使用 ValueListenableBuilder更新用户界面。 每次它侦听的值发生变化时,它都会构建特定的小部件。 它的值与听众保持同步; 即,每当值发生变化时, ValueListenable监听它并在不使用的情况下更新 UI setState()或任何其他状态管理技术:

const themeBox = 'hiveThemeBox';
void main() async {await Hive.initFlutter();await Hive.openBox(themeBox);runApp(const MyApp());
}
​
class MyApp extends StatelessWidget {const MyApp({Key? key}) : super(key: key);
​@overrideWidget build(BuildContext context) {//to update the UI without using setState()return ValueListenableBuilder(valueListenable: Hive.box(themeBox).listenable(),builder: (context, box, widget) {//saving the value inside the hive box,var darkMode = Hive.box(themeBox).get('darkMode', defaultValue: false);return MaterialApp(debugShowCheckedModeBanner: false,//switching between light and dark theme,themeMode: darkMode ? ThemeMode.dark : ThemeMode.light,title: 'Flutter Demo',darkTheme: ThemeData.dark(),home: HomePage(value: darkMode,));},);}
}
​
class HomePage extends StatelessWidget {final bool value;const HomePage({Key? key, required this.value}) : super(key: key);
​@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: Text(value ? 'Hive Dark Mode' : 'Hive Light Mode'),actions: [Switch(value: value,onChanged: (val) {Hive.box(themeBox).put('darkMode', !value);},),],),body: Padding(padding: const EdgeInsets.all(8.0),child: Column(crossAxisAlignment: CrossAxisAlignment.stretch,children: [ ],),),);}
}

切换小部件示例

在这里,我们将看看在我们的应用程序中实现切换小部件的四种不同方法。

  • 单一且必需:用户必须从两个选项中选择至少一个

  • 单一且不需要:用户无需选择任何选项

  • Multiple and required:用户必须至少选择一个给定选项,但也可以选择多个选项

  • 多选且非必选:用户可以根据需要选择或取消选择,也可以选择多个选项

首先,让我们看一下切换小部件的标准属性以对其进行自定义,然后我们将查看每个小部件的代码及其插图:

ToggleButtons(// list of booleansisSelected: isSelected,// text color of selected toggleselectedColor: Colors.white,// text color of not selected togglecolor: Colors.blue,// fill color of selected togglefillColor: Colors.lightBlue.shade900,// when pressed, splash color is seensplashColor: Colors.red,// long press to identify highlight colorhighlightColor: Colors.orange,// if consistency is needed for all text styletextStyle: const TextStyle(fontWeight: FontWeight.bold),// border properties for each togglerenderBorder: true,borderColor: Colors.black,borderWidth: 1.5,borderRadius: BorderRadius.circular(10),selectedBorderColor: Colors.pink,
// add widgets for which the users need to togglechildren: [ ],
// to select or deselect when pressedonPressed: (int newIndex) { }
);

单个和必需的拨动开关

首先,我们必须初始化一个布尔变量列表:

// one must always be true, means selected.
List<bool> isSelected = [true, false, false];

由于我们强制系统始终选择至少一个选项,因此我们将一个值初始化为 true.

我们已经讨论了自定义切换小部件的其他属性。 现在我们将子小部件添加到它的 children财产。

注意,您必须添加与布尔值列表相同数量的子小部件。 否则会抛出错误。

// add widgets for which the users need to toggle
children: const [Padding(padding: EdgeInsets.symmetric(horizontal: 12),child: Text('MALE', style: TextStyle(fontSize: 18)),),Padding(padding: EdgeInsets.symmetric(horizontal: 12),child: Text('FEMALE', style: TextStyle(fontSize: 18)),),Padding(padding: EdgeInsets.symmetric(horizontal: 12),child: Text('OTHER', style: TextStyle(fontSize: 18)),),
],

接下来,我们必须将逻辑添加到 onPressed()内部切换小部件的属性 setState()功能。

  • 使用 for循环,我们将遍历布尔值列表

  • 使用

    if

    声明,我们将检查

    index

    值并始终将其设置为

    true

    . 其他按钮将设置为

    false
    onPressed: (int newIndex) {setState(() {// looping through the list of booleans valuesfor (int index = 0; index < isSelected.length; index++) {// checking for the index valueif (index == newIndex) {// one button is always set to trueisSelected[index] = true;} else {// other two will be set to false and not selectedisSelected[index] = false;}}});
    },

这就是我们最终产品的外观。


来自 LogRocket 的更多精彩文章:

  • 不要错过 The Replay 来自 LogRocket 的精选时事通讯

  • 了解 LogRocket 的 Galileo 如何消除噪音以主动解决应用程序中的问题

  • 使用 React 的 useEffect 优化应用程序的性能

  • 之间切换 在多个 Node 版本

  • 了解如何 使用 AnimXYZ 为您的 React 应用程序制作动画

  • 探索 Tauri ,一个用于构建二进制文件的新框架

  • 比较 NestJS 与 Express.js


单个且不需要的拨动开关

我们只需要进行两项更改即可使其正常工作。 用户只能从三个选项中选择一个,但不是必须选择它。

布尔变量列表中的值都初始化为 false:

// all values are false
List<bool> isSelected = [false, false, false];

在 - 的里面 if statement in the onPressed() function, we only toggle between buttons to set it to true:

onPressed: (int newIndex) {setState(() {// looping through the list of booleans valuesfor (int index = 0; index < isSelected.length; index++) {if (index == newIndex) {// toggling between the button to set it to trueisSelected[index] = !isSelected[index];} else {// other two buttons will not be selected and are set to falseisSelected[index] = false;}}});
},

需要多选

如前所述,用户可以选择多个选项,但系统将始终保持至少一个选项处于选中状态。

是的,您猜对了,布尔值列表中的一个值将是 true:

List<bool> isSelected = [true, false, false];

里面的事情变得有点有趣 onPressed功能。

首先,我们添加一个变量来循环布尔值列表,并确保值为真; 因此,始终至少选择一个按钮:

final isOneSelected = isSelected.where((element) => element).length == 1;

如果只选择了一个按钮,则用户无法将其切换到 false直到选择另一个选项:

if (isOneSelected && isSelected[newIndex]) return;

接下来,内 setState()函数,我们再次遍历我们的列表,检查新的索引值,并在新旧索引之间切换:

setState(() {// looping through the list of booleansfor (int index = 0; index < isSelected.length; index++) {// checking for the index valueif (index == newIndex) {// toggle between the old index and new index valueisSelected[index] = !isSelected[index];}}
});

不需要的多项选择

这很简单。 我制作了一行文本编辑选项,您通常在任何文本编辑器中都会看到这些选项来格式化书面文本。 有四个选项,所以我们的列表中有四个值,并且都设置为 false:

List<bool> isSelected = [false, false, false, false];

在我们的 onPressed()功能,我们只需在 true和 false价值观:

onPressed: (int index) {setState(() {// simply toggling buttons between true and false stateisSelected[index] = !isSelected[index];});

我们已经完成了对开关和切换小部件以及如何以通常方式使用它的解释。 现在,让我们通过创建一个自定义动画开关按钮来进行一些复杂的编程,在实现下一个代码集后,该按钮将如下图所示。

创建自定义动画开关按钮

我们将此按钮分为两部分。 第一个是我命名为的无状态小部件 CustomAnimatedSwitch. 在这个无状态小部件中,我们将创建自定义开关。 稍后,我们会将它添加到有状态小部件中以使用 setState()功能来打开和关闭。

简壁纸App,全是4K壁纸超给力,极品内容已全部解锁!

第一步:添加依赖

simple_animations: ^5.0.0+2

第 2 步:定义变量

首先,我们将使用枚举和布尔值定义命名常量变量:

enum _CustomSwitchParams { paddingLeft, color, text, rotation }final bool toggle;

其次,由于我们使用的是带有级联符号(双点运算符)的简单动画包,因此我们在 MovieTween我们为访问其属性而创建的对象。 基本上,我们正在向我们之前添加的枚举添加动画:

var customTween = MovieTween()..scene(duration: const Duration(seconds: 1)).tween(_CustomSwitchParams.paddingLeft, 0.0.tweenTo(60.0))..scene(duration: const Duration(seconds: 1)).tween(_CustomSwitchParams.color, Colors.red.tweenTo(Colors.green))..scene(duration: const Duration(milliseconds: 500)).tween(_CustomSwitchParams.text, ConstantTween('OFF')).thenTween(_CustomSwitchParams.text, ConstantTween('ON'),duration: const Duration(milliseconds: 500))..scene(duration: const Duration(seconds: 1)).tween(_CustomSwitchParams.rotation, (-2 * pi).tweenTo(0.0));

第 3 步: CustomAnimationBuilder

接下来,我们将构建我们的 CustomAnimationBuilder小部件并定义其所需的属性来组装开关动画:

CustomAnimationBuilder<Movie>(// control of the animationcontrol: toggle ? Control.play : Control.playReverse,// the relative position where animation will startstartPosition: toggle ? 1.0 : 0.0,// define unique keykey: const Key('0'),duration: customTween.duration * 1.2,// movie tween objecttween: customTween,curve: Curves.easeInOut,builder: (context, value, child) {return Container(decoration:_outerDecoration(color: value.get(_CustomSwitchParams.color)),width: 100.0,height: 40.0,padding: const EdgeInsets.all(4.0),child: Stack(children: [Positioned(child: Padding(padding: EdgeInsets.only(left: value.get(_CustomSwitchParams.paddingLeft),),child: Transform.rotate(angle: value.get(_CustomSwitchParams.rotation),child: Container(decoration: _innerDecoration(color: value.get(_CustomSwitchParams.color),),width: 30.0,child: Center(child: Text(value.get(_CustomSwitchParams.text),style: const TextStyle(height: 1.5,fontSize: 12,fontWeight: FontWeight.bold,color: Colors.white),),),),),),),],),);},);
}

第4步: CustomSwitchButton(有状态小部件)

来到创建自定义开关按钮的第二部分,我们必须添加另一个包含有状态小部件的 Dart 文件,我们将其称为 CustomSwitchButton.

首先,定义一个布尔变量并将其值设置为 false:

bool _switched = false;

其次,创建一个方法 setState()切换功能 true和 false:

void toggleSwitch() {setState(() {_switched = !_switched;});
}

最后,我们添加我们的 CustomAnimatedSwitch到这个包裹着的 Dart 文件 GestureDetector,添加 toggleSwitch的方法 onTap()功能。

而已! 我们拥有功能齐全的定制动画开关按钮。 请查看下面的代码和图像:

@overrideWidget build(BuildContext context) {return Scaffold(appBar: AppBar(title: const Text('Custom Animated Switch'),),body: GestureDetector(onTap: toggleSwitch,child: Center(child: Column(crossAxisAlignment: CrossAxisAlignment.center,mainAxisAlignment: MainAxisAlignment.center,children: [const Padding(padding: EdgeInsets.all(10.0),child: Text('Tap to Check Custom Animated Switch'),),const SizedBox(height: 20.0,),CustomAnimatedSwitch(toggle: _switched),],),),),);}
}

用于开关和切换的流行 Flutter 包

如果您不想创建自己的开关按钮,您可以随时使用以下任何包,它们的功能与我们制作自己的自定义动画开关完全相同。

  1. AnimatedToggleSwitch:用于多种选择的简单和动画切换开关。 如果您不想使用下拉菜单之类的东西,这是一个不错的选择

  2. FlutterSwitch:为 Flutter 创建的易于实现的自定义开关。 给它一个自定义的高度和宽度,开关和切换的边框,边框半径,颜色,切换大小,显示 开 和 关 文本的选择,并能够在切换内添加一个图标

  3. ToggleSwitch:一个简单的切换开关小部件。 它可以完全自定义所需的图标、宽度、颜色、文本、圆角半径、动画等。它还保持选择状态

我留下了 整个项目的链接 ,你可以在我的 GitHub 页面上找到它。 如果有任何问题或者您可以改进代码,请告诉我,我会让您访问我的项目。

非常感谢并保持安全!

LogRocket :全面了解您的网络和移动应用程序

LogRocket 是一个前端应用程序监控解决方案,可让您重现问题,就好像它们发生在您自己的浏览器中一样。 无需猜测错误发生的原因,或要求用户提供屏幕截图和日志转储,LogRocket 可让您重播会话以快速了解问题所在。 无论框架如何,它都可以完美地与任何应用程序配合使用,并且具有用于记录来自 Redux、Vuex 和 @ngrx/store 的附加上下文的插件。

除了记录 Redux 操作和状态之外,LogRocket 还记录控制台日志、JavaScript 错误、堆栈跟踪、带有标头 + 正文的网络请求/响应、浏览器元数据和自定义日志。 它还检测 DOM 以记录页面上的 HTML 和 CSS,即使是最复杂的单页和移动应用程序也能重新创建像素完美的视频。

Flutter 开关和切换高级指南相关推荐

  1. RabbitMQ 高级指南:从配置、使用到高可用集群搭建

    博主说:在项目中,通过 RabbitMQ,咱们可以将一些无需即时返回且耗时的操作提取出来,进行异步处理,而这种异步处理的方式大大的节省了服务器的请求响应时间,从而提高了系统的吞吐量. 正文 1 Rab ...

  2. Android左右滑动控件实现开关的切换效果

    /**  * 开关控件,通过左右滑动控件实现开关的切换效果 <br>  * 使用时需要设置开关状态监听{@link OnSwitchStateChangeListener} <br& ...

  3. Vue3官网-高级指南(十五)Vue 与 Web Components

    Vue3官网-高级指南(十五)Vue 与 Web Components 文章目录 Vue3官网-高级指南(十五)Vue 与 Web Components 1. Vue 与 Web Components ...

  4. win下使用fvm实现多个Flutter版本的切换

    win下使用fvm实现多个Flutter版本的切换 配置前说明:Win环境下,下载FVM时,需要先配置一个Dart环境,因为用到 dart pub命令 配置Dart环境 a. 方式一:可以去Dart官 ...

  5. 可视化大屏设计尺寸_大屏可视化设计尺寸高级指南

    原标题:大屏可视化设计尺寸高级指南 大屏可视化的设计尺寸定义,一直是很多设计师苦恼的一件事,很多时候大屏出现的问题,都是因为对设计尺寸没有一个正确的认识导致.比如大屏内容呈现不全.拉伸.压缩.字号小的 ...

  6. Vue3官网-高级指南(十七)响应式计算`computed`和侦听`watchEffect`(onTrack、onTrigger、onInvalidate、副作用的刷新时机、`watch` 、pre)

    Vue3官网-高级指南(十七)响应式计算computed和侦听watchEffect(onTrack.onTrigger.onInvalidate.副作用的刷新时机.watch .pre).渲染机制和 ...

  7. flutter 开关Switch与复选框Checkbox

    Flutter 移动跨平台开发技术分享 目前在西瓜视频上免费刊登 Flutter 系列教程,每日更新,欢迎关注接收提醒 [x1]点击查看提示 [x2]各种系列的教程 [x3]Flutter文章积累目录 ...

  8. 使用FVM管理Flutter SDK版本切换

    window下配置fvm版本切换工具,管理flutter sdk版本的切换 一.配置flutter dart环境 使用前需要先配置flutter dart环境,才能下载jvm 已经配置好环境的,在命令 ...

  9. axure选中后横线切换_3、开关状态切换 —— Axure实用交互

    写在开头:开关的制作在几乎所有原型设计中都会用到,所以美观自然的交互开关可以给你的原型设计加分不少. 本次开关设计主要用到的是逻辑为:选中状态的切换 首先,来看一下演示动画 开始原型设计 一.创建元件 ...

最新文章

  1. Spring MVC+Stomp+Security+H2 Jetty
  2. python找字符串_Python如何实现查找字符串
  3. WindowsServer和普通WIN操作系统有什么不同?
  4. 一张图系列——为什么在DllMain里面创建了线程并Wait会卡死
  5. 遍历map几种方式及应用
  6. 1010 Radix
  7. 算法设计与分析——回溯法——旅行售货员问题
  8. 工具类—KeyValuePair
  9. Alexey 大神接棒,YOLOv4 重磅来袭!快来一睹论文真容吧!| 原力计划
  10. Linux -单用户模式(忘记Linux的root密码)
  11. 何时创建MVC应用程序
  12. HTML/CSS 面试总结
  13. Vc6.0打开该文件坠毁
  14. 螺纹螺母的直径和牙数备忘
  15. L1-4 拯救外星人
  16. iOS录屏直播(二)Broadcast Upload Extension和Broadcast Setup UI Extension
  17. 内卷的国货彩妆下,完美日记还能“火”多久?
  18. 肖博老师高中数学必备知识点总结最全版
  19. 计算机两个硬盘的作用,电脑装2个硬盘有什么好处与坏处
  20. 小程序停止html5音乐,微信小程序API 音乐播放控制

热门文章

  1. 激活神器!KMSpico v10.2.0 正式版本
  2. 【Spring boot 项目实践】基于Spring boot 的外卖系统
  3. 英语不好,英语不好真的可以学编程吗?亲身经历告诉你
  4. Luogu P5069 [Ynoi2015] 纵使日薄西山
  5. .NET框架-Try-Parse和Tester-Doer
  6. C#编译基础知识(一)
  7. 洛伦兹力的matlab求解,问:由安培力推导洛伦兹力的过程?
  8. 学习英特尔线程构建模块开源2.1库
  9. 雷锋网专访陌陌产品总监雷小亮
  10. 把图片按照图片名字分到不同的文件夹中