플로우
플로우
Flow
- FlowDelegate 의 로직에 따라 하위 요소의 크기와 위치를 효율적으로 지정하는 위젯
- 주로 사용하는 속성
- FlowDelegate delegate
- children의 변환 행렬을 제어하는 대리자
- 필수
- List
children - 내부에 배치될 위젯 목록
- 기본 값 : const
[]
- FlowDelegate delegate
- 참고
class FlowMenu extends StatefulWidget {
const FlowMenu({super.key});
@override
State<FlowMenu> createState() => _FlowMenuState();
}
class _FlowMenuState extends State<FlowMenu> with SingleTickerProviderStateMixin {
late AnimationController menuAnimation; //애니메이션을 제어하기 위한 컨트롤러
IconData lastTapped = Icons.notifications; //마지막으로 선택한 아이콘
final List<IconData> menuItems = <IconData>[ Icons.home, Icons.new_releases, Icons.notifications, Icons.settings, Icons.menu, ]; //아이콘 목록
//메뉴 변경
void _updateMenu(IconData icon) {
if (icon != Icons.menu) {
setState(() => lastTapped = icon);
}
}
@override
void initState() {
super.initState();
menuAnimation = AnimationController(
duration: const Duration(milliseconds: 250), //250ms동안 애니메이션 동작
vsync: this,
);
}
//메뉴 위젯
Widget flowMenuItem(IconData icon) {
final double buttonDiameter = MediaQuery.of(context).size.width / menuItems.length; //버튼 크기
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: RawMaterialButton(
fillColor: lastTapped == icon ? Colors.amber[700] : Colors.blue,
splashColor: Colors.amber[100],
shape: const CircleBorder(),
constraints: BoxConstraints.tight(Size(buttonDiameter, buttonDiameter)),
onPressed: () {
_updateMenu(icon); //메뉴 변경
menuAnimation.status == AnimationStatus.completed ? menuAnimation.reverse() : menuAnimation.forward(); //애니메이션 동작
},
child: Icon(
icon,
color: Colors.white,
size: 45.0,
),
),
);
}
@override
Widget build(BuildContext context) {
return Flow(
delegate: FlowMenuDelegate(menuAnimation: menuAnimation), //대리자 지정
children: menuItems.map<Widget>((IconData icon) => flowMenuItem(icon)).toList(),
);
}
}
class FlowMenuDelegate extends FlowDelegate {
FlowMenuDelegate({required this.menuAnimation}) : super(repaint: menuAnimation);
final Animation<double> menuAnimation;
@override
bool shouldRepaint(FlowMenuDelegate oldDelegate) {
return menuAnimation != oldDelegate.menuAnimation;
}
@override
void paintChildren(FlowPaintingContext context) {
double dx = 0.0;
for (int i = 0; i < context.childCount; ++i) {
dx = context.getChildSize(i)!.width * i;
context.paintChild(i, transform: Matrix4.translationValues(dx * menuAnimation.value, 0, 0,), );
}
}
} 이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.