인프런 커뮤니티 질문&답변

bubble gun님의 프로필 이미지

작성한 질문수

[코드팩토리] [중급] Flutter 진짜 실전! 상태관리, 캐시관리, Code Generation, GoRouter, 인증로직 등 중수가 되기 위한 필수 스킬들!

GoNamed 함수

네스팅 방식으로 goRouter Go를 사용할때, 앱바타이틀이 정상적으로 표시되지 않는 문제

작성

·

384

0

GoRouter 초반부를 듣고 있는데, 제목과 같이 앱바타이틀이 정상적으로 표시되지 않는 문제를 겪고 있습니다.

Screen Three 로 이동했을때 앱바의 타이틀은
/one/two/three 로 표기가 되나,
뒤로가기를 눌렀을때 홈으로 이동할때까지 그 상태 그대로
/one/two/three 가 유지되다가 홈에서 / 로 표시가 됩니다.

OneScreen, TwoScreen, ThreeScreen 별로 각각 텍스트로 one, two, three 라고 입력해서 확인해본결과,
뒤로가기 할때마다 three 에서 출발해서 two, one 으로 화면에 잘 뜨는 것으로 보아 페이지 이동은 정상적으로 이루어지는 것 같습니다.

아래는 default_layout.dart 입니다.

class DefaultLayout extends StatelessWidget {
  final Widget body;

  const DefaultLayout({
    Key? key,
    required this.body,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final router = GoRouter.of(context);

    return Scaffold(
      appBar: AppBar(
        title: Text(
          router.location,
        ),
      ),
      body: Padding(
        padding: const EdgeInsets.symmetric(
          horizontal: 16.0,
        ),
        child: body,
      ),
    );
  }
}

 

main.dart

void main() {
  runApp(_App());
}

class _App extends StatelessWidget {
  _App({Key? key}) : super(key: key);

  final GoRouter _router = GoRouter(
    initialLocation: '/',
    routes: [
      GoRoute(
        path: '/',
        builder: (context, state) => const HomeScreen(),
        routes: [
          GoRoute(
            path: 'one',
            builder: (context, state) => const OneScreen(),
            routes: [
              // http://.../one/two
              GoRoute(
                path: 'two',
                builder: (context, state) => const TwoScreen(),
                routes: [
                  // http://.../one/two/three
                  GoRoute(
                    path: 'three',
                    builder: (context, state) => const ThreeScreen(),
                  ),
                ],
              )
            ],
          ),
        ],
      ),
      // http://..../one
      // http://..../two
      // GoRoute(
      //   path: '/one',
      //   builder: (context, state) => const OneScreen(),
      // ),
    ],
  );

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      theme: ThemeData(useMaterial3: true),
      // uri string 을 상태 및 go router 에서 사용할 수 있는 형태로 변환해주는 함수(자동)
      routeInformationParser: _router.routeInformationParser,
      // 위에서 변경된 값으로 실제 어떤 route 를 보여줄지 정하는 함수(자동)
      routerDelegate: _router.routerDelegate,
      // route 정보를 전달하는 함수(자동)
      routeInformationProvider: _router.routeInformationProvider,
    );
  }
}

 

home_screen.dart

class HomeScreen extends StatelessWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return DefaultLayout(
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          ElevatedButton(
            onPressed: () {
              context.go('/one');
            },
            child: const Text('go to OneScreen'),
          ),
          ElevatedButton(
            onPressed: () {
              context.go('/one/two/three');
            },
            child: const Text('go to ThreeScreen'),
          ),
        ],
      ),
    );
  }
}

 

3_screen.dart

class ThreeScreen extends StatelessWidget {
  const ThreeScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return DefaultLayout(
      body: Column(
        children: const [Text('three')],
      ),
    );
  }
}

정도로 참고 코드를 올렸습니다.

goRouter 버전은 4.2.2 로 강의의 버전과 맞춰서 진행중입니다.

답변 2

1

1026999님의 프로필 이미지

2023. 02. 18. 21:11

안녕하세요! GoRouter를 사용하면서 발생한 앱바 타이틀이 유지되지 않는 문제에 대해 답변드리겠습니다.

GoRouter를 사용하면 router.location을 이용해 현재 경로를 나타낼 수 있지만, 이 경로는 현재 보여지고 있는 화면의 경로와는 무관하게 GoRouter에서 가지고 있는 내부 경로 정보입니다. 그래서 이 값을 그대로 앱바 타이틀로 사용하면 화면 전환이 일어날 때마다 경로 정보가 바뀌는 문제가 발생합니다.

앱바 타이틀에 현재 화면의 이름을 나타내기 위해서는, 각각의 스크린에서 SingleChildGoRouter 위젯을 이용해 GoRouter에 등록된 현재 경로 정보를 이용해 타이틀을 동적으로 변경해주어야 합니다. 이렇게 하면 화면이 전환될 때마다 현재 화면에 맞는 타이틀을 보여줄 수 있습니다.

다음은 수정된 DefaultLayout 클래스의 예시입니다.

class DefaultLayout extends StatelessWidget {

final Widget body;

const DefaultLayout({

Key? key,

required this.body,

}) : super(key: key);

@override

Widget build(BuildContext context) {

final router = GoRouter.of(context);

return Scaffold(

appBar: AppBar(

title: SingleChildGoRouter(

router: router,

builder: (BuildContext context, GoRouterState state) {

// 현재 경로에서 마지막 경로를 가져와 타이틀로 사용

final currentLocation = state.currentLocation;

final title = currentLocation.segments.last;

return Text(title);

},

),

),

body: Padding(

padding: const EdgeInsets.symmetric(

horizontal: 16.0,

),

child: body,

),

);

}

}

 

 

SingleChildGoRouter를 이용해 현재 경로의 마지막 경로를 가져와 타이틀로 사용하도록 구현했습니다. 이렇게 구현하면 화면 전환이 일어날 때마다 앱바 타이틀이 적절하게 변경됩니다.

참고로, SingleChildGoRouter는 GoRouter 내부에서 현재 경로 정보를 이용해 동적으로 위젯 트리를 구성할 때 사용하는 위젯으로, 현재 경로 정보를 이용해 앱바 타이틀 등을 동적으로 변경하는 데 매우 유용합니다.

bubble gun님의 프로필 이미지
bubble gun
질문자

2023. 02. 18. 22:24

딥변 감사드립니다.
일단 저는 SingleChildGoRouter라는 위젯이 생성이 되지 않는데, 현재 강좌 버전대비 삭제된것인지, 혹은 구현이 안되어 있는 것인지 확인해보아야겠습니다.

강좌에서 코팩님은 어떻게 해서 SingleChildGoRouter를 사용하지 않고 구현이 되었는지 궁금하긴 하네요.

상세한 원인 설명과 솔루션에 대해 감사드립니다.

 

코드팩토리님의 프로필 이미지
코드팩토리
지식공유자

2023. 02. 19. 09:39

안녕하세요. 현재 겪으시는 현상은 6.x 버전 버그입니다. 최신 버전을 한번 설치한다음에 낮은버전으로 돌아왔을경우 캐싱 문제가 있을 수 있습니다. flutter clean을 해서 프로젝트를 깔끔히 정리한다음 다시 실행 해보세요.

0

bubble gun님의 프로필 이미지
bubble gun
질문자

2023. 02. 20. 19:39

이상하네요..6.x 버전은 한 번도 깐적이 없고, 현재 4.2.2 로 강의따라 진행중인데 버그가 일어나는 것 같습니다.]

flutter clean을 해도 마찬가지인데, 일단 지금 당장 중요한것은 아니니 넘어가도록 하겠습니다. ㅜㅜ