drawer: Drawer(
backgroundColor: statusModel.darkColor,
child: ListView(
children: [
DrawerHeader(
margin: EdgeInsets.zero,
child: Text(
'지역 선택',
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
),
),
),
...Region.values
.map(
(e) => ListTile(
selected: e == region,
tileColor: Colors.white,
selectedTileColor: statusModel.lightColor,
selectedColor: Colors.black,
onTap: () {
setState(() {
region = e;
});
Navigator.of(context).pop();
},
title: Text(
e.krName,
),
),
)
.toList(),
],
),
),
enum Region {
daegu,
chungnam,
incheon,
daejeon,
gyeongbuk,
sejong,
gwangju,
jeonbuk,
gangwon,
ulsan,
jeonnam,
seoul,
busan,
jeju,
chungbuk,
gyeongnam,
gyeonggi;
String get krName {
switch (this) {
case Region.daegu:
return '대구';
case Region.chungnam:
return '충남';
case Region.incheon:
return '인천';
case Region.daejeon:
return '대전';
case Region.gyeongbuk:
return '경북';
case Region.sejong:
return '세종';
case Region.gwangju:
return '광주';
case Region.jeonbuk:
return '전북';
case Region.gangwon:
return '강원';
case Region.ulsan:
return '울산';
case Region.jeonnam:
return '전남';
case Region.seoul:
return '서울';
case Region.busan:
return '부산';
case Region.jeju:
return '제주';
case Region.chungbuk:
return '충북';
case Region.gyeongnam:
return '경남';
case Region.gyeonggi:
return '경기';
default:
throw Exception('존재하지 않는 지역 이름입니다.');
}
}
}
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
Region region = Region.seoul;
bool isExpanded = true;
ScrollController scrollController = ScrollController();
void initState() {
super.initState();
StatRepository.fetchData();
scrollController.addListener(() {
bool isExpanded = scrollController.offset < (500 - kToolbarHeight);
if(isExpanded != this.isExpanded){
setState(() {
this.isExpanded = isExpanded;
});
}
});
}
Widget build(BuildContext context) {
return FutureBuilder<StatModel?>(
future: GetIt.I<Isar>()
.statModels
.filter()
.regionEqualTo(region)
.itemCodeEqualTo(ItemCode.PM10)
.sortByDateTimeDesc()
.findFirst(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Scaffold(
body: CircularProgressIndicator(),
);
}
final statModel = snapshot.data!;
final statusModel =
StatusUtils.getStatusModelFromStat(statModel: statModel);
return Scaffold(
drawer: Drawer(
backgroundColor: statusModel.darkColor,
child: ListView(
children: [
DrawerHeader(
margin: EdgeInsets.zero,
child: Text(
'지역 선택',
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
),
),
),
...Region.values
.map(
(e) => ListTile(
selected: e == region,
tileColor: Colors.white,
selectedTileColor: statusModel.lightColor,
selectedColor: Colors.black,
onTap: () {
setState(() {
region = e;
});
Navigator.of(context).pop();
},
title: Text(
e.krName,
),
),
)
.toList(),
],
),
),
backgroundColor: statusModel.primaryColor,
body: CustomScrollView(
controller: scrollController,
slivers: [
MainStat(
region: region,
primaryColor: statusModel.primaryColor,
isExpanded: isExpanded,
),
SliverToBoxAdapter(
child: Column(
children: [
CategoryStat(
region: region,
darkColor: statusModel.darkColor,
lightColor: statusModel.lightColor,
),
HourlyStat(
region: region,
darkColor: statusModel.darkColor,
lightColor: statusModel.lightColor,
),
],
),
),
],
),
);
});
}
}
지금까지 Drawer의 간단한 설정을 알아봤습니다.
추가로 SliverAppBar 설정을 적용합니다.
AppBar 영역의 이미지가 스크롤로 사라지더라도 지역이름이 appbar에 표시됩니다.
생성자에 isExpanded 값을 받습니다.
const MainStat({
super.key,
required this.isExpanded,
});
------------------------------------------------------------
return SliverAppBar(
backgroundColor: primaryColor,
expandedHeight: 500,
pinned: true,
title: isExpanded ? null : Text('${region.krName}'),
flexibleSpace: FlexibleSpaceBar(
background: SafeArea(
...
------------------------------------------------------------
//kToolbarHeight 만큼 간격을 띄우고 이미지를 표시
return Column(
children: [
SizedBox(
height: kToolbarHeight,
),
scrollController.addListener(() {
bool isExpanded = scrollController.offset < (500 - kToolbarHeight);
if(isExpanded != this.isExpanded){
setState(() {
this.isExpanded = isExpanded;
});