Flutter 일기
참고1 : https://api.flutter.dev/flutter/material/SnackBar-class.html
참고2 : https://api.flutter.dev/flutter/material/SnackBarBehavior-class.html
SnackBar
오늘 배워볼 것은 SnackBar
화면 아래에 짧은 메시지를 보여줄 수 있고, 간단한 동작도 사용가능하다. 버튼을 넣어서 누르면 또다른 페이지로 간다던가 그런거!
나는 Getx에 입문할 때 거기서 SnackBar를 먼저 써봤는데, Getx 패키지에 있는 SnackBar는 화면 아래뿐만 아니라 위에서도 띄울 수 있고 꾸미기 기능이 좀 더 다양하다. Getx를 주로 쓰는 사람은 Get.snackbar() 를 쓰는 것을 추천한다. 하지만 나는야 기본에 충실한 개발인... 오늘은 ScaffoldMessenger에서 제공하는 SnackBar를 살펴보도록 한다.
+) Flutter 유튜브 채널에서 봤을 때는
Scaffold.of(context).showSnackBar() 의 형태로 쓰던데, 요건 이제 안 쓴다! 영상 보고나서 넣어봤더니 deprecated(더 이상 사용 안함)라고 뜬다.
코드 예시로 알아보자
공식 페이지에 나온 코드를 가져다가 뜯어보자.
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
/// This is the main application widget.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Test SnackBar')),
body: const Center(
child: MyStatelessWidget(),
),
),
);
}
}
/// This is the stateless widget that the main application instantiates.
class MyStatelessWidget extends StatelessWidget {
const MyStatelessWidget({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return SizedBox(
height: 100,
child: ElevatedButton(
child: const Text(
'Show Snackbar',
style: TextStyle(fontSize: 30),
),
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Row(
children: [
Icon(
Icons.thumb_up,
color: Colors.white,
),
SizedBox(
width: 10,
),
Expanded(
child: const Text(
'Awesome Snackbar!',
style: TextStyle(fontSize: 18),
),
),
],
),
action: SnackBarAction(
label: 'Action',
onPressed: () {
//Action 을 누르면 다른 페이지로 이동
Navigator.of(context).push(
MaterialPageRoute(builder: (context) => SecondPage()),
);
},
),
// SnackBar 유지 시간
duration: const Duration(milliseconds: 1500),
// SnackBar의 가로 길이
width: 280.0,
// Inner Padding. 값을 크게 주면 content가 차지하는 부분이 줄어들게 된다.
padding: const EdgeInsets.symmetric(
horizontal: 10.0,
),
// 얘는 좀 있다 또 알아보자
behavior: SnackBarBehavior.floating,
// SnackBar의 모양 조절
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10.0),
),
),
);
},
),
);
}
}
우선 SnackBar는 showSnackBar 로 불러줘야 한다. 예전의 AlertDialog에서 showDialog를 썼던 것과 똑같다. ^^
onPressed 부분은 허전해서 그냥 넣어보았다. 앱바 외에는 아무것도 없는 페이지를 하나 만들어서, 거기로 이동하도록 하였다.
class SecondPage extends StatelessWidget {
const SecondPage({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("SecondPage"),
),
);
}
}
정말 아무것도 없다.
실행 화면을 확인해보자.
기능 자체는 간단해서 그렇게 어렵지 않다.
다만 SnackBarBehavior 는 당장 이해가 안되서 탐색을 좀 해봤다.
behavior: SnackBarBehavior.floating,
요 부분이다. 참고 2에 가면 설명을 볼 수 있다.
우선 SnackBar 위치의 미세한 차이를 만든다.
그리고 FloatingActionButton이나 BottomNavigationBar 를 포함하고 있다면? 이 때의 SnackBar의 위치를 어떻게 할 것인가! 를 결정하는 속성이다.
FloatingActionButton과 BottomNavigationBar 둘 다 화면 하단에 뜨는 위젯이다. 요런 위젯들이 있고 behavior 속성을 변화시킬 때, SnackBar의 위치가 어떻게 달라지는지 알아보자.
FloatingActionButton은 저번에 쓴 것을 재탕하고, BottomNavigationBar는 테스트용 코드를 급하게 만들어보았다.
SnackBarBehavior.fixed
SnackBarBehavior.fixed를 쓸 때는 width 속성과 같이 쓰면 안된다.
화면 하단에 아무것도 없을 때는 화면 하단에 붙어서 나타나고, 이와 유사하게 BottomNavigationBar가 있을 때는 그 위에 찰싹 붙어서 나타난다. 반면 FloatingActionButton의 경우는 버튼을 위로 밀어올리고 그 밑에 나타난다.
아무것도 없어용 | BottomNavigationBar | FloatingActionButton |
---|---|---|
SnackBarBehavior.floating
이름처럼 살짝 둥둥 떠서 나타난다. 그리고 elevation(그림자)도 볼 수 있는데, 이 코드에는 elevation 속성을 설정하지 않았다. 설정하지 않은 경우는 기본 값은 6이다.
아무것도 없어용 | BottomNavigationBar | FloatingActionButton |
---|---|---|
위에서 사용한 예시 코드는 MyApp부분을 아래처럼 수정하고, SnackBar의 behavior 속성을 바꿔가며 사용하였다. width 속성은 아예 빼버렸다.
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Test SnackBar')),
body: const Center(
child: MyStatelessWidget(),
),
floatingActionButton: FloatingActionButton.extended(
onPressed: () {},
label: const Text('좋아요'),
icon: const Icon(Icons.thumb_up),
backgroundColor: Colors.pink,
),
// bottomNavigationBar: BottomNavigationBar(
// items: [
// BottomNavigationBarItem(
// label: 'one', icon: Icon(Icons.looks_one, color: Colors.blue)),
// BottomNavigationBarItem(
// label: 'two', icon: Icon(Icons.looks_two, color: Colors.blue)),
// ],
// ),
),
);
}
}
오늘의 일기는 여기까지!