main.dart 파일에서 body와 bottom navigation bar를 지정한 app.dart 파일을 따로 만들어서 페이지전환 관리
// 상단에 해당 페이지 파일들 임포트
import 'pages/explore.dart';
import 'pages/home.dart';
import 'pages/library.dart';
//bottom navigation bar에서 버튼이 눌릴 때 컨트롤해줄 컨트롤러 임포트
import 'package:youtube/src/controller/app_controller.dart';
class App extends GetView<Appcontroller> {
const App({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold( // scaffold로 감싼다
body: Obx(() { // Obx로 반응형 상태관리
switch(RoutName.values[controller.currentIndex.value]){
case RoutName.Home:
return Home();
break;
case RoutName.Explore:
return Explore();
break;
case RoutName.Add:
//bottom sheet
break;
case RoutName.Subs:
return Subscribe();
break;
case RoutName.Library:
return Library();
break;
}
return Container();
}),
bottomNavigationBar: Obx(
() => BottomNavigationBar(
type: BottomNavigationBarType.fixed,
currentIndex: controller.currentIndex.value,
// 반응형 인덱스 정보를 반영하기 위해 Obx로 둘러 싸고 이렇게 변경
showSelectedLabels: true,
selectedItemColor: Colors.black,
onTap: controller.changePageIndex,
// 상단 상속 받는 클래스를 GetView<Appcontroller>로 바꾸고 onTap 을 이렇게 고친다.
items: [
BottomNavigationBarItem(
icon: SvgPicture.asset('assets/svg/icons/home_off.svg'),
activeIcon: SvgPicture.asset('assets/svg/icons/home_on.svg'),
label: '홈'),
BottomNavigationBarItem(
icon: SvgPicture.asset(
'assets/svg/icons/compass_off.svg',
width: 22,
),
activeIcon: SvgPicture.asset(
'assets/svg/icons/compass_on.svg',
width: 22,
),
label: '탐색'),
BottomNavigationBarItem(
icon: Padding(
padding: const EdgeInsets.only(top: 8.0),
child: SvgPicture.asset(
'assets/svg/icons/plus.svg',
width: 35,
),
),
label: '',
),
BottomNavigationBarItem(
icon: SvgPicture.asset('assets/svg/icons/subs_off.svg'),
activeIcon: SvgPicture.asset('assets/svg/icons/subs_on.svg'),
label: '구독'),
BottomNavigationBarItem(
icon: SvgPicture.asset('assets/svg/icons/library_off.svg'),
activeIcon: SvgPicture.asset('assets/svg/icons/library_on.svg'),
label: '보관함'),
],
),
),
);
}
}
app_contoller.dart
//bottom navigation bar UI 정의 파일 임포트
import '../components/youtube_bottoms_sheet.dart';
// index를 명확히 하기 위해서 eunum 타입으로 정의
enum RoutName {Home, Explore, Add, Subs, Library}
class Appcontroller extends GetxService {
static Appcontroller get to => Get.find();
RxInt currentIndex = 0.obs; // 반응형 상태관리를 위해서 RxInt로 인덱스 설정
void changePageIndex(int index){
if (index==2){
_showBottomSheet();
}else{
currentIndex(index);
}
}
void _showBottomSheet() {
Get.bottomSheet(YoutubeBottomSheet());
}
}
bottom_sheet.dart
class YoutubeBottomSheet extends StatelessWidget {
const YoutubeBottomSheet({Key? key}) : super(key: key);
// bottom 네비게이션바 헤더 영역 정의
Widget _header() {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'만들기',
style: TextStyle(fontSize: 16),
),
IconButton(
icon: Icon(Icons.close),
onPressed: () {
Get.back();
},
)
],
);
}
// bottom 네비게이션바 버튼영역 정의
Widget _itemButton({required String icon, required double iconSize, required String label, required Function() onTap}){
return InkWell(
onTap: onTap,
child: Row(
children: [
Container(
width: 50.0,
height: 50.0,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.grey.withOpacity(0.3),
),
child: Center(
child: Container(
width: iconSize,
height: iconSize,
child: SvgPicture.asset('assets/svg/icons/$icon.svg'),
),
),
),
SizedBox(width: 15),
Text(label),
],
),
);
}
// 배경이 그레이로 바뀌면서 바닥에서 올라오는 영역 ui 설정
@override
Widget build(BuildContext context) {
return ClipRRect(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
child: Container(
padding: const EdgeInsets.only(left: 20),
height: 200,
color: Colors.white,
child: Column(
children: [
_header(),
SizedBox(
height: 10,
),
_itemButton(
icon:'upload',
iconSize: 17,
label: '동영상 업로드',
onTap: (){
print('동영상 업로드 기능');
},
),
SizedBox(
height: 10,
),
_itemButton(
icon:'broadcast',
iconSize: 25,
label: '실시간 스트리밍',
onTap: (){
print('실시간 스트리밍 기능');
},
),
],
),
),
);
}
}