Flutter动画切换插件animated_toggle的使用
Flutter动画切换插件animated_toggle的使用
Animated Toggle
Animated Toggle
为您提供了一种简单的方法来创建自定义动画切换效果。
安装
在您的 pubspec.yaml
文件中添加以下内容:
dependencies:
animated_toggle: ^Last Version
功能
- 易于使用,可以处理所有颜色、宽度和高度。
- 可以创建垂直或水平的动画切换。
- 支持从左到右或从右到左开始(适用于阿拉伯语或英语等)。
- 可以控制文本样式和动画切换的填充。
使用方法
水平动画切换
import 'package:animated_toggle/animated_toggle.dart';
import 'package:flutter/material.dart';
class MyAnimatedToggle extends StatefulWidget {
const MyAnimatedToggle({super.key});
@override
State<MyAnimatedToggle> createState() => _MyAnimatedToggleState();
}
class _MyAnimatedToggleState extends State<MyAnimatedToggle> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const Text('Animated Toggle'),
),
body: Center(
child: AnimatedHorizontalToggle(
taps: const ['First', 'Second', 'Last'],
width: MediaQuery.of(context).size.width - 40,
height: 48,
duration: const Duration(milliseconds: 300),
initialIndex: 0,
background: Colors.black.withOpacity(0.1),
activeColor: Colors.deepPurple,
activeTextStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white),
inActiveTextStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: Colors.deepPurple),
horizontalPadding: 4,
verticalPadding: 4,
activeHorizontalPadding: 2,
activeVerticalPadding: 4,
radius: 14,
activeButtonRadius: 14,
onChange: (int currentIndex, int targetIndex) {
// 写入您个人的代码
},
showActiveButtonColor: true,
local: 'en',
),
),
);
}
}
垂直动画切换
import 'package:animated_toggle/animated_toggle.dart';
import 'package:flutter/material.dart';
class MyAnimatedToggle extends StatefulWidget {
const MyAnimatedToggle({super.key});
@override
State<MyAnimatedToggle> createState() => _MyAnimatedToggleState();
}
class _MyAnimatedToggleState extends State<MyAnimatedToggle> {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: const Text('Animated Toggle'),
),
body: Center(
child: AnimatedVerticalToggle(
taps: const ['First', 'Second', 'Third', 'Last'],
width: 80,
height: 200,
duration: const Duration(milliseconds: 300),
activeButtonHeight: 34,
initialIndex: 0,
background: Colors.black.withOpacity(0.1),
activeColor: Colors.deepPurple,
activeTextStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white),
inActiveTextStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: Colors.deepPurple),
horizontalPadding: 4,
verticalPadding: 4,
activeHorizontalPadding: 4,
activeVerticalPadding: 2,
radius: 14,
activeButtonRadius: 10,
onChange: (int currentIndex, int targetIndex) {
// 写入您个人的代码
},
showActiveButtonColor: true,
local: 'en',
),
),
);
}
}
更多示例
以下是包含多个示例的完整代码:
import 'package:animated_toggle/animated_toggle.dart';
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
useMaterial3: true,
),
home: const MyAnimatedToggle(),
);
}
}
class MyAnimatedToggle extends StatefulWidget {
const MyAnimatedToggle({super.key});
@override
State<MyAnimatedToggle> createState() => _MyAnimatedToggleState();
}
class _MyAnimatedToggleState extends State<MyAnimatedToggle> {
int secondVExIndex = 0;
int secondHExIndex = 0;
int lastHExIndex = 0;
int lastVExIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.deepPurple,
title: const Text(
'Animated Toggle',
style: TextStyle(color: Colors.white),
),
),
body: Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 20.0),
child: SingleChildScrollView(
child: Column(
children: [
animatedHorizontalToggle(context),
const SizedBox(height: 30),
animatedVerticalToggle(),
],
),
),
),
),
);
}
Column animatedVerticalToggle() {
return Column(
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
AnimatedVerticalToggle(
taps: const ['First', 'Second', 'Third', 'Last'],
width: 80,
height: 200,
duration: const Duration(milliseconds: 300),
activeButtonHeight: 34,
initialIndex: 0,
background: Colors.black.withOpacity(0.1),
activeColor: Colors.deepPurple,
activeTextStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white),
inActiveTextStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: Colors.deepPurple),
horizontalPadding: 4,
verticalPadding: 4,
activeHorizontalPadding: 4,
activeVerticalPadding: 2,
radius: 14,
activeButtonRadius: 10,
onChange: (int currentIndex, int targetIndex) {},
showActiveButtonColor: true,
local: 'en',
),
AnimatedVerticalToggle(
taps: const ['First', 'Second', 'Third', 'Last'],
width: 80,
height: 200,
duration: const Duration(milliseconds: 300),
activeButtonHeight: 34,
initialIndex: 0,
background: Colors.transparent,
activeBorder: Border.all(color: Colors.black),
inActiveColor: Colors.white,
inActiveBoxShadow: [
BoxShadow(
offset: const Offset(0, 2.2),
blurRadius: 12,
color: Colors.black.withOpacity(0.08),
),
],
activeColor: Colors.deepPurple.withOpacity(0.5),
activeTextStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white),
inActiveTextStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: Colors.deepPurple),
horizontalPadding: 4,
verticalPadding: 4,
activeHorizontalPadding: 4,
activeVerticalPadding: 2,
radius: 14,
activeButtonRadius: 10,
inActiveButtonRadius: 10,
onChange: (int currentIndex, int targetIndex) {},
showActiveButtonColor: true,
local: 'en',
),
AnimatedVerticalToggle(
taps: const ['First', 'Second', 'Last'],
width: 105,
height: 200,
duration: const Duration(milliseconds: 300),
initialIndex: 0,
showPrefixIcon: true,
spaceBetweenIconAndText: 8,
prefixIcons: [
Icon(Icons.ac_unit_rounded, color: secondVExIndex == 0 ? Colors.white : Colors.deepPurple),
Icon(Icons.accessibility_new_rounded, color: secondVExIndex == 1 ? Colors.white : Colors.deepPurple),
Icon(Icons.account_balance_wallet, color: secondVExIndex == 2 ? Colors.white : Colors.deepPurple),
],
background: Colors.black.withOpacity(0.1),
activeColor: Colors.deepPurple,
activeTextStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white),
inActiveTextStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: Colors.deepPurple),
horizontalPadding: 4,
verticalPadding: 4,
activeHorizontalPadding: 4,
activeVerticalPadding: 2,
radius: 14,
activeButtonRadius: 14,
onChange: (int currentIndex, int targetIndex) {
setState(() {
secondVExIndex = currentIndex;
});
},
showActiveButtonColor: true,
local: 'en',
),
],
),
const SizedBox(height: 30),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
AnimatedVerticalToggle(
taps: const ['First', 'Second', 'Last'],
width: 90,
height: 200,
duration: const Duration(milliseconds: 300),
initialIndex: 0,
background: Colors.transparent,
activeTextStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.deepPurple),
inActiveTextStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: Colors.black),
horizontalPadding: 8,
verticalPadding: 0,
activeHorizontalPadding: 0,
activeVerticalPadding: 0,
radius: 14,
activeButtonRadius: 14,
sideLineWidth: 1,
activeSideLineWidth: 2,
onChange: (int currentIndex, int targetIndex) {},
sideLineColor: Colors.black.withOpacity(0.3),
activeSideLineColor: Colors.deepPurple,
showSideLine: true,
showActiveButtonColor: false,
local: 'en',
),
AnimatedVerticalToggle(
taps: const ['First', 'Second', 'Third', 'Last'],
width: 120,
height: 200,
duration: const Duration(milliseconds: 300),
initialIndex: 0,
showPrefixIcon: true,
spaceBetweenIconAndText: 8,
prefixIcons: [
Icon(Icons.ac_unit_rounded, color: lastVExIndex == 0 ? Colors.deepPurple : Colors.black),
Icon(Icons.accessibility_new_rounded, color: lastVExIndex == 1 ? Colors.deepPurple : Colors.black),
Icon(Icons.account_balance_wallet, color: lastVExIndex == 2 ? Colors.deepPurple : Colors.black),
Icon(Icons.account_balance, color: lastVExIndex == 3 ? Colors.deepPurple : Colors.black),
],
background: Colors.transparent,
activeTextStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.deepPurple),
inActiveTextStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: Colors.black),
horizontalPadding: 8,
verticalPadding: 0,
activeHorizontalPadding: 0,
activeVerticalPadding: 0,
radius: 14,
activeButtonRadius: 14,
sideLineWidth: 1,
activeSideLineWidth: 2,
onChange: (int currentIndex, int targetIndex) {
setState(() {
lastVExIndex = currentIndex;
});
},
sideLineColor: Colors.black.withOpacity(0.3),
activeSideLineColor: Colors.deepPurple,
showSideLine: true,
showActiveButtonColor: false,
local: 'en',
),
],
)
],
);
}
Widget animatedHorizontalToggle(BuildContext context) {
return Column(
children: [
const SizedBox(height: 30),
AnimatedHorizontalToggle(
taps: const ['First', 'Second', 'Last'],
width: MediaQuery.of(context).size.width - 40,
height: 48,
spaceBetween: 15,
duration: const Duration(milliseconds: 500),
initialIndex: 0,
background: Colors.transparent,
activeBorder: Border.all(color: Colors.black),
inActiveColor: Colors.white,
inActiveBoxShadow: [
BoxShadow(
offset: const Offset(0, 2.2),
blurRadius: 12,
color: Colors.black.withOpacity(0.08),
),
],
activeColor: Colors.deepPurple.withOpacity(0.5),
activeTextStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white),
inActiveTextStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: Colors.deepPurple),
horizontalPadding: 0,
verticalPadding: 0,
activeHorizontalPadding: 0,
activeVerticalPadding: 0,
radius: 14,
activeButtonRadius: 14,
inActiveButtonRadius: 14,
onChange: (int currentIndex, int targetIndex) {},
showActiveButtonColor: true,
local: 'en',
),
const SizedBox(height: 30),
AnimatedHorizontalToggle(
taps: const ['First', 'Second', 'Last'],
width: MediaQuery.of(context).size.width - 40,
height: 48,
duration: const Duration(milliseconds: 300),
initialIndex: 0,
background: Colors.black.withOpacity(0.1),
activeColor: Colors.deepPurple,
activeTextStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white),
inActiveTextStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: Colors.deepPurple),
horizontalPadding: 4,
verticalPadding: 4,
activeHorizontalPadding: 2,
activeVerticalPadding: 4,
radius: 14,
activeButtonRadius: 14,
onChange: (int currentIndex, int targetIndex) {},
showActiveButtonColor: true,
local: 'en',
),
const SizedBox(height: 30),
AnimatedHorizontalToggle(
taps: const ['First', 'Second', 'Last'],
width: MediaQuery.of(context).size.width - 40,
height: 48,
duration: const Duration(milliseconds: 300),
initialIndex: 0,
showPrefixIcon: true,
spaceBetweenIconAndText: 8,
prefixIcons: [
Icon(Icons.ac_unit_rounded, color: secondHExIndex == 0 ? Colors.white : Colors.deepPurple),
Icon(Icons.accessibility_new_rounded, color: secondHExIndex == 1 ? Colors.white : Colors.deepPurple),
Icon(Icons.account_balance_wallet, color: secondHExIndex == 2 ? Colors.white : Colors.deepPurple),
],
background: Colors.black.withOpacity(0.1),
activeColor: Colors.deepPurple,
activeTextStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white),
inActiveTextStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: Colors.deepPurple),
horizontalPadding: 4,
verticalPadding: 4,
activeHorizontalPadding: 2,
activeVerticalPadding: 4,
radius: 14,
activeButtonRadius: 14,
onChange: (int currentIndex, int targetIndex) {
setState(() {
secondHExIndex = currentIndex;
});
},
showActiveButtonColor: true,
local: 'en',
),
const SizedBox(height: 30),
AnimatedHorizontalToggle(
taps: const ['First', 'Second', 'Last'],
width: MediaQuery.of(context).size.width - 40,
height: 48,
duration: const Duration(milliseconds: 300),
initialIndex: 0,
background: Colors.transparent,
activeTextStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.deepPurple),
inActiveTextStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: Colors.black),
horizontalPadding: 0,
verticalPadding: 0,
activeHorizontalPadding: 0,
activeVerticalPadding: 0,
radius: 14,
activeButtonRadius: 14,
underLineHeight: 1,
activeUnderLineHeight: 2,
onChange: (int currentIndex, int targetIndex) {},
underLineColor: Colors.black.withOpacity(0.3),
activeUnderLineColor: Colors.deepPurple,
showUnderLine: true,
showActiveButtonColor: false,
local: 'en',
),
const SizedBox(height: 30),
AnimatedHorizontalToggle(
taps: const ['First', 'Second', 'Last'],
width: MediaQuery.of(context).size.width - 40,
height: 48,
duration: const Duration(milliseconds: 300),
initialIndex: 0,
showPrefixIcon: true,
spaceBetweenIconAndText: 8,
prefixIcons: [
Icon(Icons.ac_unit_rounded, color: lastHExIndex == 0 ? Colors.deepPurple : Colors.black),
Icon(Icons.accessibility_new_rounded, color: lastHExIndex == 1 ? Colors.deepPurple : Colors.black),
Icon(Icons.account_balance_wallet, color: lastHExIndex == 2 ? Colors.deepPurple : Colors.black),
],
background: Colors.transparent,
activeTextStyle: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, color: Colors.deepPurple),
inActiveTextStyle: const TextStyle(fontSize: 14, fontWeight: FontWeight.w400, color: Colors.black),
horizontalPadding: 0,
verticalPadding: 0,
activeHorizontalPadding: 0,
activeVerticalPadding: 0,
radius: 14,
activeButtonRadius: 14,
underLineHeight: 1,
activeUnderLineHeight: 2,
onChange: (int currentIndex, int targetIndex) {
setState(() {
lastHExIndex = currentIndex;
});
},
underLineColor: Colors.black.withOpacity(0.3),
activeUnderLineColor: Colors.deepPurple,
showUnderLine: true,
showActiveButtonColor: false,
local: 'en',
),
],
);
}
}
额外信息
如果您有任何需求或建议,请在GitHub上告诉我。期待更多功能的更新!
作者
希望这个详细的说明和示例代码能帮助您更好地理解和使用 animated_toggle
插件。如果有任何问题,欢迎随时提问!
更多关于Flutter动画切换插件animated_toggle的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
1 回复
更多关于Flutter动画切换插件animated_toggle的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter中使用animated_toggle
插件来实现动画切换的示例代码。animated_toggle
是一个用于创建具有动画效果的切换按钮的Flutter插件。
首先,确保你已经将animated_toggle
插件添加到了你的pubspec.yaml
文件中:
dependencies:
flutter:
sdk: flutter
animated_toggle: ^x.y.z # 请将x.y.z替换为最新版本号
然后,你可以在你的Flutter项目中这样使用它:
import 'package:flutter/material.dart';
import 'package:animated_toggle/animated_toggle.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Animated Toggle Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: ToggleScreen(),
);
}
}
class ToggleScreen extends StatefulWidget {
@override
_ToggleScreenState createState() => _ToggleScreenState();
}
class _ToggleScreenState extends State<ToggleScreen> with SingleTickerProviderStateMixin {
bool isToggled = false;
void toggle() {
setState(() {
isToggled = !isToggled;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Animated Toggle Demo'),
),
body: Center(
child: AnimatedToggle(
value: isToggled,
onToggle: toggle,
width: 100,
height: 50,
thumbColor: isToggled ? Colors.green : Colors.red,
trackColor: isToggled ? Colors.lightGreen : Colors.grey,
thumbInactiveIcon: Icon(Icons.thumb_down),
thumbActiveIcon: Icon(Icons.thumb_up),
animationDuration: Duration(milliseconds: 300),
),
),
);
}
}
代码解释:
-
导入依赖:
import 'package:flutter/material.dart';
:导入Flutter的核心Material组件。import 'package:animated_toggle/animated_toggle.dart';
:导入animated_toggle
插件。
-
主应用入口:
MyApp
类是一个无状态的Widget,它定义了应用的主题和主页。
-
主页:
ToggleScreen
是一个有状态的Widget,它管理切换按钮的状态。_ToggleScreenState
是ToggleScreen
的状态类,它包含了一个布尔值isToggled
来跟踪切换按钮的状态。
-
切换按钮:
AnimatedToggle
是一个自定义的切换按钮组件,它接收多个参数:value
:当前按钮的状态(开或关)。onToggle
:当按钮被切换时调用的回调函数。width
和height
:按钮的宽度和高度。thumbColor
和trackColor
:按钮滑块和轨道的颜色。thumbInactiveIcon
和thumbActiveIcon
:按钮在关闭和打开状态下的图标。animationDuration
:动画的持续时间。
运行这个示例代码,你将看到一个带有动画效果的切换按钮,点击按钮时,它会改变颜色和图标,并且有一个平滑的动画过渡效果。