잡동사니

반응형

질문

개인 프로젝트를 위해 flutter에서 스타터 키트를 만들었습니다.

모든 것이 잘 작동하지만 Drawer에서 현재 선택한 항목을 강조 표시 할 수 없는 문제가 있습니다.

현재 선택한 항목을 결정하는 코드를 입력해야하는 위치에 대해 조금 잃어 버렸습니다. 여기에 이미지 설명 입력 여기에 이미지 설명 입력

아래는 내 코드입니다!

class _MdDrawerState extends State<MdDrawer>
    with SingleTickerProviderStateMixin<MdDrawer> {
  final _animationDuration = const Duration(milliseconds: 350);

  AnimationController _animationController;
  Stream<bool> isDrawerOpenStream;
  StreamController<bool> isDrawerOpenStreamController;
  StreamSink<bool> isDrawerOpenSink;

  .....

  @override
  void dispose() {
    _animationController.dispose();
    isDrawerOpenStreamController.close();
    isDrawerOpenSink.close();
    super.dispose();
  }

  void onIconPressed() {
    final animationStatus = _animationController.status;
    final isAnimationCompleted = animationStatus == AnimationStatus.completed;

    .....
  }

  @override
  Widget build(BuildContext context) {
    final screenWidth = MediaQuery.of(context).size.width;

    return StreamBuilder<bool>(
      initialData: false,
      stream: isDrawerOpenStream,
      builder: (context, isLeftDrawerOpenedAsync) {
        return AnimatedPositioned(
          duration: _animationDuration,
          top: 0,
          bottom: 0,
          left: isLeftDrawerOpenedAsync.data ? 0 : -screenWidth,
          right: isLeftDrawerOpenedAsync.data ? 0 : screenWidth - 45,
          child: Row(
            children: <Widget>[
              Expanded(
                child: Container(
                  padding: const EdgeInsets.symmetric(horizontal: 20),
                  color: Theme.of(context).backgroundColor,
                  child: ListView(
                    children: <Widget>[
                      Column(
                        children: <Widget>[
                          SizedBox(
                            height: 30,
                          ),
                          ListTile(
                            title: Text('First - Last',
                                style: Theme.of(context).textTheme.headline),
                            subtitle: Text('something@gmail.com',
                                style: Theme.of(context).textTheme.subhead),
                            leading: CircleAvatar(
                              child: Icon(
                                Icons.perm_identity,
                                color: Theme.of(context).iconTheme.color,
                              ),
                              radius: 40,
                            ),
                          ),
                          Divider(
                            height: 30,
                          ),
                          MdNavItem(
                            icon: Icons.home,
                            title: 'Home',
                            onTap: () {
                              onIconPressed();
                              BlocProvider.of<MdNavBloc>(context)
                                  .add(NavigationEvents.HomeClickedEvent);
                            },
                          ),
                          MdNavItem(
                            icon: Icons.account_box,
                            title: 'Account',
                            onTap: () {
                              onIconPressed();
                              BlocProvider.of<MdNavBloc>(context)
                                  .add(NavigationEvents.AccountClickedEvent);
                            },
                          ),
                          MdNavItem(
                            icon: Icons.shopping_basket,
                            title: 'Orders',
                            onTap: () {
                              onIconPressed();
                              BlocProvider.of<MdNavBloc>(context)
                                  .add(NavigationEvents.OrderClickedEvent);
                            },
                          ),
                          MdNavItem(
                            icon: Icons.card_giftcard,
                            title: 'Wishlist',
                            onTap: () {
                              onIconPressed();
                              BlocProvider.of<MdNavBloc>(context)
                                  .add(NavigationEvents.WishlistClickedEvent);
                            },
                          ),
                          Divider(
                            height: 30,
                          ),
                          MdNavItem(
                            icon: Icons.settings,
                            title: 'Settings',
                            onTap: () {
                              onIconPressed();
                              BlocProvider.of<MdNavBloc>(context)
                                  .add(NavigationEvents.SettingsClickedEvent);
                            },
                          ),
                          MdNavItem(
                            icon: Icons.exit_to_app,
                            title: 'Logout',
                          ),
                          Divider(
                            height: 45,
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
              ),
              ......
            ],
          ),
        );
      },
    );
  }
}

그리고 MdNavItem class

class MdNavItem extends StatelessWidget {
  final IconData icon;
  final String title;
  final Function onTap;

  const MdNavItem({this.icon, this.title, this.onTap});

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Container(
          color: Theme.of(context).backgroundColor,
          child: Row(
            children: <Widget>[
              Icon(
                icon,
                size: 25,
                color: Theme.of(context).iconTheme.color,
              ),
              SizedBox(
                width: 20,
              ),
              Text(
                title,
                style: Theme.of(context).textTheme.headline,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

 

답변1

Edit:

첫 번째 방법 :

Drawer에 다음 코드를 추가하세요.

class _MdDrawerState extends State<MdDrawer>
    with SingleTickerProviderStateMixin<MdDrawer> {
  final _animationDuration = const Duration(milliseconds: 350);

  AnimationController _animationController;
  Stream<bool> isDrawerOpenStream;
  StreamController<bool> isDrawerOpenStreamController;
  StreamSink<bool> isDrawerOpenSink;


  final List<bool> isTaped = [true, false, false, false, false];  // the first is true because when the app
                                                                  //launch the home needs to be in red(or the
                                                                  //color you choose)

  void changeHighlight(int index){
    for(int indexTap = 0; indexTap < isTaped.length; indexTap++) {
      if (indexTap == index) {
        isTaped[index] = true;                                    //used to change the value of the bool list
      } else {
        isTaped[indexTap] = false;
      }
    }
  }

  .....

  @override
  void dispose() {
    _animationController.dispose();
    isDrawerOpenStreamController.close();
    isDrawerOpenSink.close();
    super.dispose();
  }

  void onIconPressed() {
    final animationStatus = _animationController.status;
    final isAnimationCompleted = animationStatus == AnimationStatus.completed;

    .....
  }

  @override
  Widget build(BuildContext context) {
    final screenWidth = MediaQuery.of(context).size.width;

    return StreamBuilder<bool>(
      initialData: false,
      stream: isDrawerOpenStream,
      builder: (context, isLeftDrawerOpenedAsync) {
        return AnimatedPositioned(
          duration: _animationDuration,
          top: 0,
          bottom: 0,
          left: isLeftDrawerOpenedAsync.data ? 0 : -screenWidth,
          right: isLeftDrawerOpenedAsync.data ? 0 : screenWidth - 45,
          child: Row(
            children: <Widget>[
              Expanded(
                child: Container(
                  padding: const EdgeInsets.symmetric(horizontal: 20),
                  color: Theme.of(context).backgroundColor,
                  child: ListView(
                    children: <Widget>[
                      Column(
                        children: <Widget>[
                          SizedBox(
                            height: 30,
                          ),
                          ListTile(
                            title: Text('First - Last',
                                style: Theme.of(context).textTheme.headline),
                            subtitle: Text('something@gmail.com',
                                style: Theme.of(context).textTheme.subhead),
                            leading: CircleAvatar(
                              child: Icon(
                                Icons.perm_identity,
                                color: Theme.of(context).iconTheme.color,
                              ),
                              radius: 40,
                            ),
                          ),
                          Divider(
                            height: 30,
                          ),
                          MdNavItem(
                            wasTaped: isTaped[0],
                            icon: Icons.home,
                            title: 'Home',
                            onTap: () {
                              onIconPressed();
                              BlocProvider.of<MdNavBloc>(context)
                                  .add(NavigationEvents.HomeClickedEvent);
                              changeHighlight(0);
                            },
                          ),
                          MdNavItem(
                            wasTaped: isTaped[1],
                            icon: Icons.account_box,
                            title: 'Account',
                            onTap: () {
                              onIconPressed();
                              BlocProvider.of<MdNavBloc>(context)
                                  .add(NavigationEvents.AccountClickedEvent);
                              changeHighlight(1);
                            },
                          ),
                          MdNavItem(
                            wasTaped: isTaped[2],
                            icon: Icons.shopping_basket,
                            title: 'Orders',
                            onTap: () {
                              onIconPressed();
                              BlocProvider.of<MdNavBloc>(context)
                                  .add(NavigationEvents.OrderClickedEvent);
                              changeHighlight(2);
                            },
                          ),
                          MdNavItem(
                            wasTaped: isTaped[3],
                            icon: Icons.card_giftcard,
                            title: 'Wishlist',
                            onTap: () {
                              onIconPressed();
                              BlocProvider.of<MdNavBloc>(context)
                                  .add(NavigationEvents.WishlistClickedEvent);
                              changeHighlight(3);
                            },
                          ),
                          Divider(
                            height: 30,
                          ),
                          MdNavItem(
                            wasTaped: isTaped[4],
                            icon: Icons.settings,
                            title: 'Settings',
                            onTap: () {
                              onIconPressed();
                              BlocProvider.of<MdNavBloc>(context)
                                  .add(NavigationEvents.SettingsClickedEvent);
                              changeHighlight(4);
                            },
                          ),
                          MdNavItem(
                            icon: Icons.exit_to_app,
                            title: 'Logout',
                          ),
                          Divider(
                            height: 45,
                          ),
                        ],
                      ),
                    ],
                  ),
                ),
              ),
              ......
            ],
          ),
        );
      },
    );
  }
}

그리고 이것은 MdNavItem에 :

class MdNavItem extends StatelessWidget {
  final IconData icon;
  final String title;
  final Function onTap;
  final bool wasTaped;     //receiving the bool value (if was taped or not)

  const MdNavItem({this.icon, this.title, this.onTap, this.wasTaped});

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Container(
          color: Theme.of(context).backgroundColor,
          child: Row(
            children: <Widget>[
              Icon(
                icon,
                size: 25,
                color: wasTaped ? Colors.red : Theme.of(context).iconTheme.color, //the condition to change the color
              ),
              SizedBox(
                width: 20,
              ),
              Text(
                title,
                style: wasTaped ? TextStyle(
                  color: Colors.red,
                ) : Theme.of(context).textTheme.headline,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

이전 답변, 두 번째 방법 :

PageView가 배치된 첫 번째 화면 :

class FirstScreen extends StatelessWidget {

  final PageController pageController = PageController(initialPage: 0);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Kit App'),
      ),
      drawer: CustomDrawer(
        pageController: pageController,
      ),
      body: PageView(
        controller: pageController,
        physics: NeverScrollableScrollPhysics(), //to prevent scroll
        children: <Widget>[
          HomeScreen(),
          AccountScreen(),   //your pages
          OrdersScreen(),
          WishListScreen(),
        ],
      ),
    );
  }
}

CustomDrawer :

class CustomDrawer extends StatelessWidget {
  CustomDrawer({@required this.pageController});

  final PageController pageController;

  @override
  Widget build(BuildContext context) {
    return Drawer(
      child: Padding(
        padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 20),
        child: Column(
          children: <Widget>[
            DrawerItem(
              onTap: (){
                Navigator.pop(context); //to close the drawer
                pageController.jumpToPage(0);
              },
              leading: Icons.home,
              title: 'Home',
              index: 0,
              controller: pageController,
            ),
            DrawerItem(
              onTap: (){
                Navigator.pop(context);
                pageController.jumpToPage(1);
              },
              leading: Icons.account_box,
              title: 'Account',
              index: 1,
              controller: pageController,
            ),
            DrawerItem(
              onTap: (){
                Navigator.pop(context);
                pageController.jumpToPage(2);
              },
              leading: Icons.shopping_cart,
              title: 'Orders',
              index: 2,
              controller: pageController,
            ),
            DrawerItem(
              onTap: (){
                Navigator.pop(context);
                pageController.jumpToPage(3);
              },
              leading: Icons.card_travel,
              title: 'Wishlist',
              index: 3,
              controller: pageController,
            ),
          ],
        ),
      ),
    );
  }
}

항목의 색상을 변경하기 위한 조건이 있는 DrawerItem :

class DrawerItem extends StatelessWidget {
  DrawerItem({
    @required this.onTap,
    @required this.leading,
    @required this.title,
    @required this.index,
    @required this.controller,
  });

  final VoidCallback onTap;
  final IconData leading;
  final String title;
  final int index;
  final PageController controller;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: onTap,
      child: ListTile(
        leading: Icon(
          leading,
          color: controller.page.round() == index ? Colors.red : Colors.grey,
        ),
        title: Text(
          title,
          style: TextStyle(
            color: controller.page.round() == index ? Colors.red : Colors.grey,
          ),
        ),
      ),
    );
  }
}

결과: 여기에 이미지 설명 입력

이제 코드에 이것을 구현하기만 하면 됩니다.



 

 

 

 

출처 : https://stackoverflow.com/questions/60803116/flutter-highlight-current-selected-nav-item

반응형

이 글을 공유합시다

facebook twitter googleplus kakaoTalk kakaostory naver band