본문 바로가기

Flutter

Body, Bottom 영역 지정 및 페이지 전환 파일

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('실시간 스트리밍 기능');
              },
            ),
          ],
        ),
      ),
    );
  }
}