지난번 글에서는 Flutter을 이용하여 기본적인 프론트엔드 디자인을 하는 방법을 알아보았다.
[Flutter] (4) 프론트엔드 디자인 하기 (Front-end Design)
지난번 글에서 Flutter의 기본 구조에 대해서 알아보았다. [Flutter] (3) Dart의 기본 구조 알아보기 [Flutter] (2) 애뮬리이터 설치하기, 앱 빌드 및 웹 빌드 이번 글에서는 Flutter에서 개발한 코드를 안드
hwanho-log.tistory.com
하지만 글 마지막 부분에서 나는 고정된 숫자 사이즈의 한계를 느낄 수 있었다.
Container의 사이즈를 숫자로 특정하여서 입력을 하게되니 화면의 사이즈가 바뀌었을 때 동적으로 반응을 하지 못하고 UI에러가 발생하는 것을 확인 할 수 있었다.
이를 해결하기 위해서는 MediaQuery라는 함수를 사용하면 편하게 사이즈의 변화에 따라 특정한 컴포넌트들의 크기를 설정할 수 있다.
MediaQuery 사용하기
body: Column(
children: [
Container(
height: 300,
child: Row(
children: [
Container(color: const Color.fromARGB(255, 255, 64, 252), width: 300,),
Container(color: Color.fromARGB(255, 252, 251, 252), width: 300,)
],
),
),
Container(color: Colors.amberAccent, height: 100,),
Container(color: const Color.fromARGB(255, 0, 0, 0),height: 100),
Container(color: Color.fromARGB(255, 25, 155, 202),height: 100)
]
),
);
}
}
지난번에 작성했던 위와 같은 코드를 MediaQuery를 사용하여 아래와 같이 바꾸었다.
body: Column(
children: [
Container(
height: MediaQuery.of(context).size.height/2,
child: Row(
children: [
Container(color: const Color.fromARGB(255, 255, 64, 252), width: MediaQuery.of(context).size.width/2,),
Container(color: Color.fromARGB(255, 252, 251, 252), width: MediaQuery.of(context).size.width/2,)
],
),
),
Container(color: Colors.amberAccent, height: MediaQuery.of(context).size.height/6,),
Container(color: const Color.fromARGB(255, 0, 0, 0),height: MediaQuery.of(context).size.height/6),
Container(color: Color.fromARGB(255, 25, 155, 202),height: MediaQuery.of(context).size.height/6)
]
),
);
}
}
결과 화면을 확인해보면 MediaQuery를 사용하지 않은 코드와 똑같은 화면이 나온다는 것을 확인할 수 있다.
한가지 다른점이 있다면 MediaQuery를 사용한 코드는 화면 사이즈를 바꿔도 에러가 나지 않고 화면 크기에 맞춰서 동적으로 컴포넌트들의 크기를 조절해준다는 것이다!
** 한가지 주의할 점은, MediaQuery를 통해서 가져온 크기는 사용자의 디바이스 크기임으로, Appbar의 크기를 포함한다.
그래서 만약 Appbar가 존재한다면, 단순 비율로 나눠서 크기를 설정하는 것은 조금 어려움이 있을 수 있다. (이 경우 MediaQuery뒤에 Appbar의 높이만큼 빼준는 연산을 실행한 뒤에 비율로 나누면 해결할 수 있다)
**LayoutBuilder을 사용하면 된다! 이는 아래에서 자세히 설명하도록 하겠다.
MediaQuery를 사용하는 기본 형태는 MediaQuery.of(context).____으로 사용하면 된다.
1. MediaQuery.of(context).size
-> 사용자 디바이스의 가로 세로 크기를 구해준다.
2. MediaQuery.of(context).size.width
-> 사용자 디바이스의 가로 길이(폭)를 구해준다.
3. MediaQuery.of(context).size.height
-> 사용자 디바이스의 세로 길이(높이)를 구해준다.
4. MediaQuery.of(context).orientation
-> 사용자 디바이스의 방향을 구해준다.
-> 출력값은 orientation.portrait 혹은, orientation.landscape 이다.
이렇게 MediaQuery를 사용하면 사용자 디바이스의 크기 등을 알아낼 수 있다.
하지만 만약 전체 화면 정보가 아닌 각각의 위젯들에 대한 사이즈나 정보를 알고 싶을 때는 어떻게 해야할까?
1. MediaQuery를 사용한다.
-> MediaQuery를 사용하여 각 위젯의 정보를 알아낼 수도 있다. MediaQuery.of(____) 원래 context에 해당하던 _____ 자리에 원하는 위젯의 리턴값을 넣어주면 된다. 하지만 이와같은 방법은 복잡하고 어려워 추천하지 않는다.
2. LayoutBuilder을 사용한다.
-> LayoutBuilder은 body, child 함수등에서 사용될 수 있고, 하위 함수로 "builder: " 을 가진다. 해당 builder 함수는 builder: (BuildContext context, BoxConstraints constraints) 의 형식으로 호출되는데 여기서 리턴하는 context, constraints를 사용하여 각 위젯의 정보를 알 수 있다.
-> 대표적으로 constraints.maxWidth, constrints.maxHeight 등을 사용하여 가로 세로 길이를 알 수 있다.
**Builder종류를 사용할 때에는 반드시 위젯을 return해주어야 한다!
이 LayoutBuilder을 사용하여 아까 경험하였던 문제를 해결하였다.
위에서 MediaQuery를 사용해 색상 박스를 나눌 때, Appbar의 높이까지 포함한 값을 리턴해주기 때문에 추가 연산을 필요로 하거나 Appar을 없애야 했는데, LayoutBuilder을 사용하면 아래 코드와 같이 Appbar을 추가하고도 Container을 일정한 비율로 나누어 줄 수 있다.
LayoutBuilder 사용하기
Widget build(BuildContext context){
return Scaffold(
backgroundColor: const Color.fromARGB(255, 136, 194, 223),
appBar: AppBar(
backgroundColor: Color.fromARGB(255, 219, 234, 248),
title: Text('My Page', style: TextStyle(color: Color.fromARGB(255, 1, 71, 136))),
centerTitle: true,
leading: IconButton(icon: Icon(Icons.menu),onPressed: null),
actions: [
IconButton(icon: Icon(Icons.battery_saver),onPressed: null),
IconButton(icon: Icon(Icons.ac_unit),onPressed: null),
IconButton(icon: Icon(Icons.hls),onPressed: null),
],
),
body: LayoutBuilder(
builder: (BuildContext context, BoxConstraints constraints){
return Column(
children: [
Container(
height: constraints.maxHeight/2,
child: Row(
children: [
Container(color: const Color.fromARGB(255, 255, 64, 252), width: constraints.maxWidth/2,),
Container(color: Color.fromARGB(255, 252, 251, 252), width: constraints.maxWidth/2,)
],
),
),
Container(color: Colors.amberAccent, height: constraints.maxHeight/6,),
Container(color: const Color.fromARGB(255, 0, 0, 0),height: constraints.maxHeight/6),
Container(color: Color.fromARGB(255, 25, 155, 202),height: constraints.maxHeight/6)
]
);
}
),
);
}
위와 같이 Appbar을 추가하고도 올바른 비율로 Container이 나누어진 것을 확인할 수 있다.
추가적으로 LayoutBuilder과 비슷하게 OrientationBuilder라는 것도 존재하는데, 사용자 디바이스의 방향을 확인하여 방향에 따라서 다른 위젯을 리턴해줄 수 있다. 사용방법은 LayoutBuiler과 비슷하게 body나 child같은 곳에서 호출해주고 builder: (BuildContext context, Orientation orientation) 함수를 사용하면 된다. 이는 아래 코드와 같이 사용해줄 수 있다.
OrientationBuilder 사용하기
if(orientation == Orientation.portrait){
___execute 1____
}else if(orientation == Orientation.landscape){
___execute 2____
}
적응형 페이지 (Adaptive Layout) vs. 반응형 페이지 (Responsive User Interface)
위에서 사용한 MediaQuery, Layoutbuilder등의 위젯은 결국 적응형 페이지 (Adaptive Layout) 혹은 반응형 페이지 (Responsive User Interface)를 만들기 위한 위젯이라고 할 수 있다.
두 개념은 정말 비슷하게 섞여서 사용될때가 많지만, 자세히 생각해보면 완전히 다른 개념이다.
적응형 페이지 (Adaptive Layout) | 반응형 페이지 (Responsive User Interface) |
1. 사용자 디바이스 상태에 따라서 UI가 변화됨 2. UI를 조금 더 사용자 친화적으로 만들 수 있음 |
|
- 각각의 화면 크기에 맞는 레이아웃 버전을 별도로 만들어야 함 | - 화면에 사이즈에 따라서 동적으로 UI 사이즈 등이 변화함 (여러가지 레이아웃 버전을 만들 필요가 없음) |
이렇게 단편적으로 본다면 무조건 반응형 페이지가 좋아보일 수 있지만, 실제로 개발을 진행하다보면 적응형 페이지를 사용함으로 더 좋은 UI를 만들 수 있는 경우가 생긴다.
그렇기 때문에 개발 상황과 목적에 맞게 잘 선택하여 사용하는 것이 중요할 것 같다.
다음글 바로가기
[Flutter] (6) Open Source Package (오픈소스 패키지): url_launcher, Screen Util 사용하기
지난번 글까지는 Flutter 내부에 있는 위젯과 함수들을 사용하여 UI 디자인을 시작해보았다. [Flutter] (5) MediaQuery, LayoutBuilder, OrienataionBuilder 사용하기 지난번 글에서는 Flutter을 이용하여 기본적인 프
hwanho-log.tistory.com
'Study Log > Flutter' 카테고리의 다른 글
[Flutter] (7) GridView, 문자열 내 코드 실행, 삼항연산자 사용하기 (0) | 2023.07.11 |
---|---|
[Flutter] (6) Open Source Package (오픈소스 패키지): url_launcher, Screen Util 사용하기 (0) | 2023.07.10 |
[Flutter] (4) 프론트엔드 디자인 하기 (Front-end Design) (0) | 2023.06.26 |
[Flutter] (3) Flutter & Dart의 기본 구조 알아보기 (0) | 2023.06.24 |
[Flutter] (2) 애뮬리이터 설치하기, 앱 빌드 및 웹 빌드 (1) | 2023.06.19 |