1.让界面之间可以嵌套且执行动画。
2.界面的添加遵循先进后出原则。
3.需要使用AnimateView,请看我上一篇博客。
演示:
代码:
Stack:
import 'package:flutter/cupertino.dart';
///栈,先进后出
class KqWidgetStack {
final List<Widget> _stack = [];
///入栈
push(Widget obj) {
_stack.add(obj);
}
///出栈
Widget? pop() {
if (_stack.isEmpty) {
return null;
} else {
return _stack.removeLast();
}
}
///栈长度
length() {
return _stack.length;
}
///清除栈
clear() {
_stack.clear();
}
}
StackView:
import 'package:flutter/cupertino.dart';
import 'package:kq_flutter_widgets/widgets/animate/animate_view.dart';
import 'package:kq_flutter_widgets/widgets/stackview/stack.dart';
class StackView extends StatefulWidget {
///初始显示的界面
final Widget initChild;
///state回调。获取state后方便后续界面操作。
final void Function(StackViewState state)? stateCallback;
const StackView({
super.key,
required this.initChild,
this.stateCallback,
});
@override
State<StatefulWidget> createState() => StackViewState();
}
class StackViewState extends State<StackView> {
final KqWidgetStack _stack = KqWidgetStack();
bool _isOpen = true;
Widget? _previousWidget;
Widget? _currentWidget;
@override
void initState() {
super.initState();
_currentWidget = widget.initChild;
widget.stateCallback?.call(this);
}
@override
Widget build(BuildContext context) {
if (_currentWidget == null) {
return Container();
} else if (_previousWidget == null) {
return _isOpen
? AnimateView(
animate: TranslationAnimate(
angle: TranslationAnimateDirection.bottomToTop.angle,
type: TranslationAnimateType.translateIn),
child: _currentWidget!,
)
: AnimateView(
animate: TranslationAnimate(
angle: TranslationAnimateDirection.topToBottom.angle,
type: TranslationAnimateType.translateOut),
child: _currentWidget!,
);
} else {
return _isOpen
? Stack(
children: [
AnimateView(
animate: TranslationAnimate(
angle: TranslationAnimateDirection.bottomToTop.angle,
type: TranslationAnimateType.translateOut),
isNeedFlashEveryTime: true,
child: _previousWidget!,
),
AnimateView(
animate: TranslationAnimate(
angle: TranslationAnimateDirection.bottomToTop.angle,
type: TranslationAnimateType.translateIn),
isNeedFlashEveryTime: true,
child: _currentWidget!,
),
],
)
: Stack(
children: [
AnimateView(
animate: TranslationAnimate(
angle: TranslationAnimateDirection.topToBottom.angle,
type: TranslationAnimateType.translateOut),
isNeedFlashEveryTime: true,
child: _previousWidget!,
),
AnimateView(
animate: TranslationAnimate(
angle: TranslationAnimateDirection.topToBottom.angle,
type: TranslationAnimateType.translateIn),
isNeedFlashEveryTime: true,
child: _currentWidget!,
),
],
);
}
}
addWidget(Widget page) {
_isOpen = true;
_previousWidget = _currentWidget;
_currentWidget = page;
if (_previousWidget != null) {
_stack.push(_previousWidget!);
}
print("stack size=${_stack.length()}");
setState(() {});
}
///回退,返回上一个界面。
///[bool] 返回true表示成功返回上一级,
///返回false表示返回失败,已是最后一个界面,不可继续返回。
bool back() {
_isOpen = false;
_previousWidget = _currentWidget;
_currentWidget = _stack.pop();
print("stack size=${_stack.length()}");
setState(() {});
if (_stack.length() > 1) {
return true;
} else {
return false;
}
}
@override
void dispose() {
super.dispose();
_stack.clear();
}
}
demo:
import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:kq_flutter_widgets/widgets/button/kq_small_button.dart';
import 'package:kq_flutter_widgets/widgets/stackview/stack_view.dart';
import 'package:kq_flutter_widgets/widgets/titleBar/kq_title_bar.dart';
class StackViewDemo extends StatefulWidget {
const StackViewDemo({super.key});
@override
State<StatefulWidget> createState() => StackViewDemoState();
}
class StackViewDemoState extends State<StackViewDemo> {
StackViewState? state;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: KqHeadBar(
headTitle: 'StackView演示',
back: () {
Get.back();
},
),
body: StackView(
initChild: Column(
children: [
const Text("我是首页"),
KqSmallButton(
title: "打开新页面",
onTap: (disabled) {
state?.addWidget(TestPage1(state: state!));
},
),
Expanded(child: Container(color: Colors.purple,)),
],
),
stateCallback: (StackViewState state) {
this.state = state;
},
),
);
}
}
class TestPage1 extends StatelessWidget {
final StackViewState state;
const TestPage1({super.key, required this.state});
@override
Widget build(BuildContext context) {
return Column(
children: [
const Text("我是TestPage1"),
KqSmallButton(
title: "返回",
onTap: (disabled) {
state.back();
},
),
KqSmallButton(
title: "打开新页面",
onTap: (disabled) {
state.addWidget(TestPage2(state: state));
},
),
Expanded(child: Container(color: Colors.amber,)),
],
);
}
}
class TestPage2 extends StatelessWidget {
final StackViewState state;
const TestPage2({super.key, required this.state});
@override
Widget build(BuildContext context) {
return Column(
children: [
const Text("我是TestPage2"),
KqSmallButton(
title: "返回",
onTap: (disabled) {
state.back();
},
),
KqSmallButton(
title: "打开新页面",
onTap: (disabled) {
state.addWidget(TestPage3(state: state));
},
),
Expanded(child: Container(color: Colors.cyan,)),
],
);
}
}
class TestPage3 extends StatelessWidget {
final StackViewState state;
const TestPage3({super.key, required this.state});
@override
Widget build(BuildContext context) {
return Column(
children: [
const Text("我是TestPage3"),
KqSmallButton(
title: "返回",
onTap: (disabled) {
state.back();
},
),
Expanded(child: Container(color: Colors.blueAccent,)),
],
);
}
}