플러터 공부/코드팩토리 인강 기록
플러터 - DefaultLayout 으로 쉽게 레이아웃 통일하기
Lee_SH
2023. 6. 13. 22:50
DefaultLayout
프로젝트 규모가 커지다보면 수많은 페이지들과 스크린들이 만들어진다. 만약 모든 스크린들에 공통적으로 적용하고싶은 무언가가 생긴다면 일일이 모든 스크린들에 들어가 코드를 수정,추가 해주어야하는 번거로움이 생긴다.
import 'package:flutter/material.dart';
class DefaultLayout extends StatelessWidget {
final Widget child;
const DefaultLayout({
required this.child,
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
body: child,
);
}
}
따라서 DefaultLayout이라는 클래스를 따로 만들고,
import 'package:code_factory_2_practice/common/layout/default_layout.dart';
import 'package:flutter/material.dart';
class LoginScreen extends StatelessWidget {
const LoginScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return DefaultLayout(child: child);
}
}
각 스크린들을 DefaultLayout으로 감싸는 구조로 만들어 child 파라미터로 원래 그리려던 스크린의 위젯을 넘겨준다.
그러면 DefaultLayout만 수정해주면 모든 스크린에 일괄 적용이 가능한 구조로 편하게 구성할수 있게 된다.
프로젝트 적용 예시
모든 스크린에서 사용할 DefaultLayout 생성
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import '../const/colors.dart';
class DefaultLayout extends ConsumerStatefulWidget {
final Widget child;
final String? title;
final Widget? bottomNavigationBar;
final Color? backgroundColor;
const DefaultLayout({
required this.child,
this.title,
this.bottomNavigationBar,
this.backgroundColor,
Key? key,
}) : super(key: key);
@override
ConsumerState<DefaultLayout> createState() => _DefaultLayoutState();
}
class _DefaultLayoutState extends ConsumerState<DefaultLayout> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: widget.backgroundColor,
extendBodyBehindAppBar: true,
// AppBar 뒤쪽에 화면 보일 수 있게 함.
appBar: renderAppBar(),
body: widget.child,
bottomNavigationBar: widget.bottomNavigationBar,
floatingActionButton: widget.bottomNavigationBar != null
? FloatingActionButton(
backgroundColor: PRIMARY_COLOR,
child: Icon(Icons.favorite_border_outlined),
onPressed: () {
},
)
: null,
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
);
}
AppBar? renderAppBar() {
if (widget.title == null) {
return null;
} else {
return AppBar(
title: Text(
widget.title!,
textAlign: TextAlign.center,
style: TextStyle(
fontFamily: 'Pacifico', fontSize: 30, color: Colors.white),
),
shape: const ContinuousRectangleBorder(
borderRadius: BorderRadius.only(
bottomLeft: Radius.circular(20),
bottomRight: Radius.circular(20)),
),
elevation: 0,
// backgroundColor: Colors.transparent,
);
}
}
}
코드에 RiverPod 적용을 위해 기본 flutter material widget 코드가 변형되있음
ConsumerStatefulWidget(riverpod 사용을 위한 위젯) -> Statefulwidget 와 동일
ConsumeState(riverpod 사용을 위한 위젯) -> State 와 동일
DefaultLayout을 사용하는 MyPageScreen
위처럼 다른 스크린에서 사용할 DefaultLayout을 정의해두고 변화하는 요소들( 상단 앱바의 타이틀명, body에 들어갈 위젯, 배경색, 바텀 네비게이션바의 존재 여부)을 파라미터로 받아주면 기본 레이아웃 구조를 통일한채로 내부 위젯과 여러 요소들을 일관성있게 보여줄수 있다.
하단 네비게이션바를 통해 완전히 다른 스크린으로 이동하더라도 다른 스크린들 또한 DefaultLayout를 기본적으로 상속한상태로 body의 위젯만 바뀌므로 동일한 레이아웃을 가진것을 알 수 있다.