[flutter] 플러터 Riverpod를 사용한 다양한 페이지 전환 방법

플러터 Riverpod는 상태 관리를 위한 라이브러리로, 다양한 페이지 간의 전환을 구현하는 데 유용합니다. 이번 글에서는 Riverpod를 사용하여 플러터 앱에서 다양한 페이지 전환 방법을 소개합니다.

목차

  1. 페이지 전환을 위한 패키지 설치
  2. 네비게이션 스택 기반의 페이지 전환
  3. 페이드 효과를 가진 페이지 전환
  4. 슬라이드 효과를 가진 페이지 전환

1. 페이지 전환을 위한 패키지 설치

플러터 앱에서 페이지 전환을 구현하기 위해 먼저 다음 패키지를 설치해야 합니다.

dependencies:
  flutter:
    sdk: flutter
  riverpod: ^1.0.4
  flutter_hooks: ^0.18.0

2. 네비게이션 스택 기반의 페이지 전환

플러터에서 가장 일반적인 페이지 전환 방식은 네비게이션 스택을 사용하는 것입니다. 이를 위해 Navigator 클래스를 사용할 수 있습니다. 다음은 Riverpod와 Navigator를 사용하여 페이지 전환을 구현하는 예시 코드입니다.

import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:riverpod/riverpod.dart';

final _currentPageProvider = StateProvider<int>((ref) => 0);

void main() {
  runApp(
    ProviderScope(
      child: MyApp(),
    ),
  );
}

class MyApp extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final currentPage = useProvider(_currentPageProvider).state;

    return MaterialApp(
      home: Navigator(
        pages: [
          MaterialPage(child: Screen1()),
          if (currentPage == 1) MaterialPage(child: Screen2()),
          if (currentPage == 2) MaterialPage(child: Screen3()),
        ],
        onPopPage: (route, result) {
          if (!route.didPop(result)) {
            return false;
          }

          context.read(_currentPageProvider).state--;
          return true;
        },
      ),
    );
  }
}

class Screen1 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Screen 1')),
      body: Center(
        child: ElevatedButton(
          child: Text('Go to Screen 2'),
          onPressed: () {
            context.read(_currentPageProvider).state = 1;
          },
        ),
      ),
    );
  }
}

class Screen2 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Screen 2')),
      body: Center(
        child: ElevatedButton(
          child: Text('Go to Screen 3'),
          onPressed: () {
            context.read(_currentPageProvider).state = 2;
          },
        ),
      ),
    );
  }
}

class Screen3 extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('Screen 3')),
      body: Center(
        child: ElevatedButton(
          child: Text('Go back to Screen 2'),
          onPressed: () {
            context.read(_currentPageProvider).state = 1;
          },
        ),
      ),
    );
  }
}

3. 페이드 효과를 가진 페이지 전환

페이드 효과를 가진 페이지 전환은 애니메이션을 사용하여 부드럽게 페이지를 전환하는 방식입니다. Riverpod와 PageRouteBuilder를 사용하여 페이드 효과를 가진 페이지 전환을 구현할 수 있습니다. 다음은 페이드 효과를 가진 페이지 전환을 구현하는 예시 코드입니다.

// 이전 코드 생략...

class MyApp extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final currentPage = useProvider(_currentPageProvider).state;

    return MaterialApp(
      home: Navigator(
        pages: [
          MaterialPage(child: Screen1()),
          if (currentPage == 1) FadeTransitionPage(child: Screen2()),
          if (currentPage == 2) FadeTransitionPage(child: Screen3()),
        ],
        onPopPage: (route, result) {
          if (!route.didPop(result)) {
            return false;
          }

          context.read(_currentPageProvider).state--;
          return true;
        },
      ),
    );
  }
}

class FadeTransitionPage extends Page {
  final Widget child;

  FadeTransitionPage({required this.child}) : super(key: ValueKey(child));

  @override
  Route createRoute(BuildContext context) {
    return PageRouteBuilder(
      settings: this,
      pageBuilder: (context, animation, secondaryAnimation) {
        return FadeTransition(
          opacity: animation,
          child: child,
        );
      },
    );
  }
}

// 이후 코드 생략...

4. 슬라이드 효과를 가진 페이지 전환

슬라이드 효과를 가진 페이지 전환은 페이지가 화면으로 슬라이드되는 애니메이션을 사용하는 방식입니다. Riverpod와 PageRouteBuilder를 사용하여 슬라이드 효과를 가진 페이지 전환을 구현할 수 있습니다. 다음은 슬라이드 효과를 가진 페이지 전환을 구현하는 예시 코드입니다.

// 이전 코드 생략...

class MyApp extends HookWidget {
  @override
  Widget build(BuildContext context) {
    final currentPage = useProvider(_currentPageProvider).state;

    return MaterialApp(
      home: Navigator(
        pages: [
          MaterialPage(child: Screen1()),
          if (currentPage == 1) SlideTransitionPage(child: Screen2()),
          if (currentPage == 2) SlideTransitionPage(child: Screen3()),
        ],
        onPopPage: (route, result) {
          if (!route.didPop(result)) {
            return false;
          }

          context.read(_currentPageProvider).state--;
          return true;
        },
      ),
    );
  }
}

class SlideTransitionPage extends Page {
  final Widget child;

  SlideTransitionPage({required this.child}) : super(key: ValueKey(child));

  @override
  Route createRoute(BuildContext context) {
    return PageRouteBuilder(
      settings: this,
      pageBuilder: (context, animation, secondaryAnimation) {
        return SlideTransition(
          position: Tween<Offset>(
            begin: Offset(1.0, 0.0),
            end: Offset.zero,
          ).animate(animation),
          child: child,
        );
      },
    );
  }
}

// 이후 코드 생략...

위에서 소개한 세 가지 방법을 통해 플러터 앱에서 다양한 페이지 전환을 구현할 수 있습니다. Riverpod를 활용하여 상태 관리도 쉽게 처리할 수 있으므로, 앱의 사용자 경험을 향상시키기 위해 페이지 전환을 적절히 활용해보세요.

참고 자료