8일차 과제 링크 👉 8일차 과제
TextButton(
onPressed: () {},
child: Text('text button'),
),
ElevatedButton(
onPressed: () {},
child: Text('elevated button'),
),
OutlinedButton(
onPressed: () {},
child: Text('outlined button'),
),
IconButton(
onPressed: () {},
icon: Icon(Icons.abc_sharp),
),
💡 버튼 디자인을 할 때 고려해야 하는 것
데스크탑에서는 커서를 이용해 클릭하지만 모바일 상에서는 커서가 아닌 손가락으로 클릭을 하게 된다.
→ 손가락은 사람마다 크기가 다르기 때문에 사용자가 터치해야하는 터치 포인트의 크기를 적절히 잘 설정해야 한다!
- 최소 7mm, 적당하게는 11-13mm
- 최소 26px, 적당하게는 42-49px
- 애플에서는 44pt, 구글은 48dp로 추천하고 있음
- dp : 안드로이드의 기본 단위
- pt : iOS의 기본 단위
- 기기마다 픽셀의 밀도(해상도)가 달라서 표현되는 길이가 각각 다름
- dp와 pt를 사용하면 기기마다의 차이를 고민하지 않고도 인터페이스를 디자인 할 수 있다
InkWell(
onTap: () {
print('야호');
},
child: Text('text'),
),
GestureDetector(
onTap: () {
print('야호');
},
child: Text('text'),
),
// FAB 누르면 텍스트 안녕 -> 반갑습니다 변경
class MyApp extends StatefulWidget {
const MyApp({super.key});
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String message = '안녕';
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
message = '반갑습니다';
setState(() {});
},
child: Icon(Icons.change_circle),
),
body: Center(
child: Text(message),
),
)
);
}
}
// text 클릭 시 level 1씩 증
class MyApp extends StatefulWidget {
const MyApp({super.key});
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
int level = 1;
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: InkWell(
onTap: () {
level ++;
setState(() {});
},
child: Center(
child: Text('현재 $level레벨 입니다'),
),
),
)
);
}
}
createState()
: StatefulWidget 인스턴스가 만들어질 때 한 번만 호출되며, 해당 위젯에 상응하는 State 객체를 생성한다.initState()
: State 객체가 생성된 후, Stateful 위젯의 초기화 작업을 수행한다. 이 메소드는 한 번만 호출되며, 다른 상태 변경 이벤트에 의해 다시 호출되지 않는다.didChangeDependencies()
: 위젯이 의존하는 객체들의 상태가 변경될 때마다 호출된다. 이 메소드는 initState() 메소드 이후에 호출되며, 여러 번 호출될 수 있다.build()
: 위젯을 빌드하고 화면에 표시하기 위한 위젯 트리를 생성한다. 이 메소드는 initState() 이후에 최초로 호출되며, 상태 변경이 발생할 때마다 호출된다.setState()
: State 객체의 상태를 변경할 때 사용한다. 이 메소드를 호출하면 Flutter 프레임워크는 State 객체의 build() 메소드를 다시 호출하여 UI를 업데이트한다.didUpdateWidget()
: 위젯이 새로운 속성값을 받게 되면 호출된다. 이 메소드는 위젯이 업데이트되면서 호출될 뿐, 초기 렌더링 시에는 호출되지 않는다.deactivate()
: State 객체가 위젯 트리에서 제거되기 전에 호출된다. 이 때 해당 위젯은 화면에 보이지 않지만 여전히 메모리에 존재한다.dispose()
: State 객체가 영구적으로 제거되기 전에 호출된다. 해당 위젯이 더 이상 필요하지 않을 때, 메모리에서 해제하기 위한 작업을 수행한다. 이 메소드는 initState() 이후에 최초로 한 번만 호출된다.class MyApp extends StatefulWidget { // StatefulWidget 상속받기
const MyApp({super.key});
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
// ...음악 객체 담겨있는 리스트 변수 musicList 선언... //
int tapIdx = 0; // 클릭한 ListTile의 index 정보가 담겨있는 변수
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
home: Scaffold(
backgroundColor: Colors.black,
appBar: AppBar(//...//),
body: ListView.builder(
shrinkWrap: true,
itemCount: musicList.length,
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
setState(() { // 클릭 시 tapIdx에 index 값 대입하고 rebuild
tapIdx = index;
});
},
child: MusicTile(
imgUrl: musicList[index].imgUrl,
title: musicList[index].title,
singer: musicList[index].singer,
time: musicList[index].time,
),
);
},
),
bottomNavigationBar: BottomNavigationBar(//...//),
bottomSheet: Container(
height: 70,
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: Colors.grey,
width: 1
)
)
),
child: ListTile(
// 보여줄 음악의 리스트 index를 tapIdx로 수정
leading: Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(5),
),
clipBehavior: Clip.antiAlias,
child: Image.asset(musicList[tapIdx].imgUrl),
),
title: Text(musicList[tapIdx].title, maxLines: 2, overflow: TextOverflow.ellipsis),
subtitle: Text(musicList[tapIdx].singer, overflow: TextOverflow.ellipsis),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Icon(Icons.play_arrow),
),
Icon(Icons.skip_next),
],
),
),
),
)
);
}
}
금요일은 역시 과제가 많네요
재밌겠다...