【Flutter/Dart】画面遷移処理

目次

概要

アプリを作る上で基本となる画面遷移処理を記載していく。
画面左上に戻るボタンが出てくる画面遷移(ここではPush遷移と言おう)と、前の画面に戻れない画面遷移(ここではPresent遷移と言おう)を実装する。
前者は通常の画面遷移、後者はログイン後などに使えるだろう。

Push遷移

ソースコード

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import 'package:concentration/TransitionView/TopView.dart';

void main() async{

  runApp(ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepOrange),
        useMaterial3: true,
      ),
      home: TopView(),
    );
  }
}

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import 'SubView.dart';

class TopView extends ConsumerWidget {
  const TopView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Scaffold(
        appBar: AppBar(
          backgroundColor: Theme.of(context).colorScheme.inversePrimary,
          title: Text("遷移前の画面"),
        ),
        body: Container(
          alignment: Alignment.center,
          child: ElevatedButton(
            onPressed: () {
              Navigator.push(
                  context,
                  MaterialPageRoute(builder: (context) => SubView())
              );
            },
            style: ElevatedButton.styleFrom(
              foregroundColor: Colors.white,
              backgroundColor: Colors.red,
              elevation: 5,
            ),
            child: Text("画面遷移するよ!"),
          ),
        )
    );
  }
}
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

class SubView extends ConsumerWidget {
  const SubView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Scaffold(
        appBar: AppBar(
          backgroundColor: Theme.of(context).colorScheme.inversePrimary,
          title: Text("遷移後の画面"),
        ),
        body: Container(
          alignment: Alignment.center,
          child: Text("新たなる大地"),
        )
    );
  }
}

デモ動画

Present遷移

ソースコード

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import 'package:concentration/TransitionView/TopView.dart';

void main() async{

  runApp(ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepOrange),
        useMaterial3: true,
      ),
      home: TopView(),
    );
  }
}
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import 'SubView.dart';

class TopView extends ConsumerWidget {
  const TopView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Scaffold(
        appBar: AppBar(
          backgroundColor: Theme.of(context).colorScheme.inversePrimary,
          title: Text("遷移前の画面"),
        ),
        body: Container(
          alignment: Alignment.center,
          child: ElevatedButton(
            onPressed: () {
              Navigator.pushReplacement(
                  context,
                  MaterialPageRoute(builder: (context) => SubView())
              );
            },
            style: ElevatedButton.styleFrom(
              foregroundColor: Colors.white,
              backgroundColor: Colors.red,
              elevation: 5,
            ),
            child: Text("画面遷移するよ!"),
          ),
        )
    );
  }
}
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

class SubView extends ConsumerWidget {
  const SubView({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    return Scaffold(
        appBar: AppBar(
          backgroundColor: Theme.of(context).colorScheme.inversePrimary,
          title: Text("遷移後の画面"),
        ),
        body: Container(
          alignment: Alignment.center,
          child: Text("新たなる大地"),
        )
    );
  }
}

デモ動画

詳細

画面遷移を行う時は以下のように行う。
前の画面に戻れるようにするには前者を、前の画面に戻れなくするには後者を使う。

ただ、前の画面に戻れなくなるといっても、画面の置き換えなので、それ以前の画面へは戻ることはできる。
その際は

Navigator.push(
    context,
    MaterialPageRoute(builder: (context) => SubView())
);
Navigator.pushReplacement(
    context,
    MaterialPageRoute(builder: (context) => SubView())
);

第一引数にbuildメソッドのcontextを、第二引数にMaterialPageRouteを使って遷移先の画面のオブジェクトを設定することで画面遷移ができる。
MaterialPageRouteというのはMaterialAppがルートの場合に使われる画面遷移で、
アニメーションを自分で設定したい時はPageRouteBuilderを継承して独自に作る必要があるようだ。

参考ページ