Flutter折叠与展开动画插件origami的使用
Flutter折叠与展开动画插件origami的使用
Origami
Origami是一个用于构建服务器驱动UI的Flutter库。它允许你使用JSON定义UI组件及其配置,从而实现动态UI更新而无需更改代码。
使用场景
作为移动开发者,我们经常需要尽快交付应用程序。此外,UI变化可能每周都会发生。然而,如果出现bug或者需要修改UI,我们需要发布更新后的应用到应用商店,这需要时间和成本。因此,我们需要构建灵活的页面。所以,我们定义了一个轻量级的UI协议,并在Android和iOS上实现了它。我们可以通过推送一个json文件来动态更新应用UI。有了这个能力,我们可以在不发布应用到应用商店的情况下进行一些UI A/B测试。通过这个项目,你可以从一个json字符串(即UI协议)构建你的UI。json字符串非常类似于Flutter小部件的dart代码。所有的小部件类型和小部件属性都是相同的。
安装
要在你的Flutter项目中使用Origami,请遵循以下步骤:
- 将Origami库添加到你的
pubspec.yaml
文件中:
flutter pub add origami
示例
这是一个使用Origami构建服务器驱动UI的简单示例。
服务器
{
"type": "scaffold",
"appBar": {
"type": "appBar",
"title": {"type": "text", "text": "Login"},
},
"body": {
"type": "safeArea",
"child": {
"type": "column",
"crossAxisAlignment": "center",
"children": [
{
"type": "sizedBox",
"height": "20.0",
},
{
"type": "image",
"imageType": "network",
"value":
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRjSoKn8IQb33N82TB_LkwVNhgHmlqTuZTcWA&usqp=CAU",
"height": "100.0",
},
{
"type": "container",
"padding": {
"edgeInsetsGeometry": "all",
"value": "16.0",
},
"child": {
"type": "column",
"crossAxisAlignment": "center",
"children": [
{
"type": "textFormField",
"decoration": {
"labelText": "Username",
"hintText": "Enter your username",
}
},
{
"type": "textFormField",
"decoration": {
"labelText": "Password",
"hintText": "Enter your password",
}
},
{
"type": "sizedBox",
"height": "30.0",
},
{
"type": "elevatedButton",
"child": {"type": "text", "text": "Login"},
},
],
},
},
{
"type": "text",
"text": "Forgot password?",
"style": {"color": "#3366CC", "fontSize": "16.0"},
},
],
}
},
}
Flutter
import 'package:flutter/material.dart';
import 'package:origami/origami.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
[@override](/user/override)
Widget build(BuildContext context) {
// 定义你的主题数据
ThemeData appTheme = ThemeData(
appBarTheme: const AppBarTheme(
color: Colors.amber,
),
// 添加更多的主题设置...
);
// 在OrigamiBuilder中设置主题数据
OrigamiBuilder.themeData = appTheme;
// 在主小部件状态中定义控制器映射
Map<String, dynamic> controllers = {
'username': TextEditingController(),
'password': TextEditingController(),
// 根据需要添加更多的控制器
};
// 示例JSON数据
Map<String, dynamic> jsonData = {
"type": "scaffold",
"appBar": {
"type": "appBar",
"title": {"type": "text", "text": "Login"},
},
"body": {
"type": "safeArea",
"child": {
"type": "column",
"crossAxisAlignment": "center",
"children": [
{
"type": "sizedBox",
"height": "20.0",
},
{
"type": "image",
"imageType": "network",
"value":
"https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRjSoKn8IQb33N82TB_LkwVNhgHmlqTuZTcWA&usqp=CAU",
"height": "100.0",
},
{
"type": "container",
"padding": {
"edgeInsetsGeometry": "all",
"value": "16.0",
},
"child": {
"type": "column",
"crossAxisAlignment": "center",
"children": [
{
"type": "textFormField",
"decoration": {
"labelText": "Username",
"hintText": "Enter your username",
},
"controller": "username",
"onListeners": {
"onChanged": {"method": "usernameChanged"},
"onFieldSubmitted": {"method": "usernameSubmitted"}
}
},
{
"type": "textFormField",
"decoration": {
"labelText": "Password",
"hintText": "Enter your password",
},
"obscureText": "true",
"controller": "password",
},
{
"type": "sizedBox",
"height": "30.0",
},
{
"type": "elevatedButton",
"onPressed": {
"method": "loginButtonPressed",
"params": {
"username": "exampleUsername",
"password": "examplePassword",
}
},
"child": {"type": "text", "text": "Login"},
},
],
},
},
{
"type": "text",
"text": "Forgot password?",
"style": {"color": "#3366CC", "fontSize": "16.0"},
},
{
"type": "sizedBox",
"height": "30.0",
},
{
"type": "customWidget1",
},
{
"type": "customWidget2",
},
],
}
},
};
// 注册默认构造器
OrigamiBuilder.registerCustomBuildersFromJsonList([
{
"type": "customWidget1",
"builder": (BuildContext context, Map<String, dynamic> data,
{Map<String, dynamic>? controllers,
Function(dynamic params)? onMethodCall,
Map<String, Function(dynamic params)>? onListeners}) {
return const Text("Your Dynamic Widget");
}
},
{
"type": "customWidget2",
"builder": (BuildContext context, Map<String, dynamic> data,
{Map<String, dynamic>? controllers,
Function(dynamic params)? onMethodCall,
Map<String, Function(dynamic params)>? onListeners}) {
return const Text("Your Dynamic Widget 2");
}
},
// 根据需要添加更多的自定义小部件
]);
return MaterialApp(
home: OrigamiBuilder.buildFromJson(
context,
json: jsonData,
controllers: controllers,
onListeners: {
'onChanged': (dynamic params) {
// 处理'onChanged'事件
debugPrint('Text changed with parameters: $params');
},
'onFieldSubmitted': (dynamic params) {
// 处理'onFieldSubmitted'事件
debugPrint('Text changed with parameters: $params');
},
},
onMethodCall: (dynamic params) {
// 根据方法名处理不同的方法调用
if (params != null && params['method'] != null) {
String methodName = params['method'];
Map<String, dynamic>? methodParams = params['params'];
// 根据方法名执行逻辑
switch (methodName) {
case 'loginButtonPressed':
if (methodParams != null) {
String username = controllers['username']!.text;
String password = controllers['password']!.text;
debugPrint(
"Login button pressed with username: $username, password: $password");
debugPrint(
"Login button pressed with username: $username, password: $password");
// 使用提供的参数添加你的登录逻辑
}
break;
// 根据需要添加更多的方法名案例
}
}
},
),
);
}
}
更多关于Flutter折叠与展开动画插件origami的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter折叠与展开动画插件origami的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,关于Flutter中的折叠与展开动画插件origami
的使用,这里提供一个简单的代码案例来展示其基本功能。origami
插件通常用于创建复杂的折叠和展开动画效果,不过需要注意的是,由于Flutter生态系统中的插件会随时间更新,具体的实现和API可能会有所变化。因此,以下代码基于假设的origami
插件功能进行演示。
首先,确保你的pubspec.yaml
文件中已经添加了origami
插件的依赖(请注意,这里origami
是一个假设的插件名,实际使用时请替换为真实的插件名或相应的动画插件):
dependencies:
flutter:
sdk: flutter
origami: ^x.y.z # 替换为实际版本号
然后,运行flutter pub get
来安装依赖。
接下来,在你的Dart文件中使用origami
插件来创建折叠与展开的动画效果。以下是一个简单的示例:
import 'package:flutter/material.dart';
import 'package:origami/origami.dart'; // 假设的origami插件导入
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Origami Animation Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Scaffold(
appBar: AppBar(
title: Text('Origami Animation Demo'),
),
body: Center(
child: OrigamiAnimationDemo(),
),
),
);
}
}
class OrigamiAnimationDemo extends StatefulWidget {
@override
_OrigamiAnimationDemoState createState() => _OrigamiAnimationDemoState();
}
class _OrigamiAnimationDemoState extends State<OrigamiAnimationDemo> with SingleTickerProviderStateMixin {
bool isExpanded = false;
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
TextButton(
onPressed: () {
setState(() {
isExpanded = !isExpanded;
});
},
child: Text(isExpanded ? 'Collapse' : 'Expand'),
),
SizedBox(height: 20),
AnimatedOrigami( // 假设的AnimatedOrigami是origami插件中的一个widget
expanded: isExpanded,
child: Container(
color: Colors.amber,
height: isExpanded ? 200 : 100,
child: Center(
child: Text(
'This is a foldable content.',
style: TextStyle(fontSize: 24),
),
),
),
duration: Duration(seconds: 1), // 动画持续时间
curve: Curves.easeInOut, // 动画曲线
),
],
);
}
}
// 假设的AnimatedOrigami类,实际使用时请替换为origami插件中的相应类
class AnimatedOrigami extends StatefulWidget {
final bool expanded;
final Widget child;
final Duration duration;
final Curve curve;
const AnimatedOrigami({
Key key,
@required this.expanded,
@required this.child,
this.duration = const Duration(seconds: 1),
this.curve = Curves.linear,
}) : super(key: key);
@override
_AnimatedOrigamiState createState() => _AnimatedOrigamiState();
}
class _AnimatedOrigamiState extends State<AnimatedOrigami> with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation<double> _animation;
@override
void initState() {
super.initState();
_controller = AnimationController(
duration: widget.duration,
vsync: this,
)..value = widget.expanded ? 1.0 : 0.0;
_animation = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _controller,
curve: widget.curve,
),
);
_controller.addListener(() {
setState(() {});
});
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
// 这里应该实现折叠和展开的动画逻辑,但由于origami插件是假设的,
// 我们仅简单展示如何使用动画控制器控制高度变化。
double height = lerpDouble(100, 200, _animation.value); // 假设初始高度为100,展开后为200
return AnimatedContainer(
duration: widget.duration,
curve: widget.curve,
height: height,
child: widget.child,
);
}
}
注意:
origami
插件和AnimatedOrigami
类在上面的代码中都是假设的,实际使用时需要替换为真实的插件和相应的类。- 动画效果(如折叠和展开)的实现细节会依赖于你选择的插件的具体API。
- 上面的代码仅展示了如何使用
AnimationController
和Tween
来实现简单的高度动画,实际的折叠和展开动画可能会复杂得多。
为了获得更精确和具体的实现,建议查阅所选插件的官方文档和示例代码。