일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
Tags
- 명심보감
- 오픈소스
- kotlin
- 공자명언
- Coroutine
- jetpack compose
- 이모지
- 이모지메모
- 좋은글필사하기
- Streaming
- androidx
- 넷플릭스
- Firebase
- 파이썬
- 1인개발자
- Android
- 코틀린
- recyclerview
- Freesound
- Flutter
- FSM
- 소울칼리버6
- 장자명언
- DART
- 벤자민플랭클린
- ASMR
- bash
- 명언모음
- Linux
- 공부집중
Archives
- Today
- Total
Vintage appMaker의 Tech Blog
[Flutter] Flow 위젯을 이용한 레이아웃 적용 본문
Flow 위젯은 레이아웃 위젯과 같이 자식위젯들(children)의 위치를 관리하는 위젯이다. 단지, 어떤 Rule을 정하고 그 Rule에 맞게 자식들을 재배치한다. Flow 위젯은 주로 Animation을 이용하여 FloatingButton같은 기능을 처리할 때 많이 사용된다.
1. Flow는 자식들의 위치를 raw level에서 처리한다.
2. FlowDelegatge 클래스를 상속해서 만들고 paintChildren, sholdRepaint를 오버라이드 한다.
3. raw level이다보니 스크린 전역의 값으로 위치를 지정해야 한다.
Flow를 사용하려면
Flow(
delegate: FlowDelegate을 상속받은 클래스,
children: [자식위젯들],
);
와 같이 사용하면 된다.
다음은 전체소스이다.
import 'package:flutter/material.dart';
void main() => runApp(const FlowApp());
class FlowApp extends StatelessWidget {
const FlowApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Flow 예제'),
),
body: Container(),
floatingActionButton: FlowButton(),
),
);
}
}
class FlowButton extends StatefulWidget {
const FlowButton({super.key});
@override
State<FlowButton> createState() => _FlowButtonState();
}
class _FlowButtonState extends State<FlowButton>
with SingleTickerProviderStateMixin {
late AnimationController buttonExtAni;
bool hideItem = false;
@override
void initState() {
super.initState();
buttonExtAni = AnimationController(
duration: const Duration(milliseconds: 150),
vsync: this,
)..addListener(() {
// 애니메이션 이벤트핸들러
if (buttonExtAni.status == AnimationStatus.dismissed) {
setState(() {
hideItem = true;
});
} else if (buttonExtAni.status == AnimationStatus.forward) {
setState(() {
hideItem = false;
});
}
});
}
List<Widget> buttonList() {
Widget buildItem(Widget w, [bool bAlawaysVisible = false]) {
if (bAlawaysVisible) {
hideItem = false;
}
return GestureDetector(
onTap: () {
if (buttonExtAni.status == AnimationStatus.completed) {
buttonExtAni.reverse();
} else {
buttonExtAni.forward();
}
},
child: (hideItem == true)
? Container()
: Container(
padding: EdgeInsets.all(5),
alignment: Alignment.center,
width: 50,
height: 50,
child: w),
);
}
return [
for (int i = 0; i < 3; i++)
buildItem(Text(
"$i",
style: TextStyle(color: Colors.black),
)),
buildItem(Icon(Icons.burst_mode), true)
];
}
@override
Widget build(BuildContext context) {
return Flow(
delegate: FlowButtonDelegate(ActionAnimation: buttonExtAni),
children: [...buttonList()],
);
}
}
class FlowButtonDelegate extends FlowDelegate {
FlowButtonDelegate({required this.ActionAnimation})
: super(repaint: ActionAnimation);
final Animation<double> ActionAnimation;
@override
bool shouldRepaint(FlowButtonDelegate oldDelegate) {
return ActionAnimation != oldDelegate.ActionAnimation;
}
@override
void paintChildren(FlowPaintingContext context) {
double dy = 0.0;
for (int i = 0; i < context.childCount; ++i) {
var startX = context.size.width - 50;
var starty = context.size.height - 50;
dy = context.getChildSize(i)!.height * i + 20;
context.paintChild(
i,
transform: Matrix4.translationValues(
startX - 30,
starty - dy * ActionAnimation.value,
0,
),
);
}
}
}
'Source code or Tip > Flutter & Dart' 카테고리의 다른 글
[Flutter] 줄맞춤이 필요할 때, TextBaseline, Baseline widget (0) | 2022.12.27 |
---|---|
[Flutter] scroll시 AppBar 투명 (0) | 2022.12.23 |
[Flutter] 특정위젯만 갱신하기 - Statefulbuilder 위젯 (0) | 2022.11.30 |
[추천 유튜브] Flutter Widget을 빠르게 공부하기 (0) | 2022.11.24 |
[Flutter] firebase cli 설정시 configure 에러 (0) | 2022.11.21 |
Comments