😸

Flutterで〇〇したいチートシート

2022/10/07に公開

はじめに

初めてFlutterでアプリを作っている間に「〇〇したいけど、Flutterでどうやって書くの?」と思って調べたことをまとめただけの記事です。

外部APIを叩きたい

httpというパッケージを使う。

import 'dart:convert';
import 'package:http/http.dart' as http;

...

Future apiFunction() async {
  // URLの生成
  var url = Uri.https(
    'example.com', // ドメイン
    '/path', // パス
    {'id': 'hoge'} // クエリパラメータ
  );
  
  // ヘッダーの設定
  Map<string, string> headers = {
    'Authorization': 'Authorization Token' 
  };

  var response = await http.get(url, headers: headers);
  if (response.statusCode == 200) {
    // Success
    // JSONDecodeを使ってレスポンスをデコードする
    var jsonResponse = jsonDecode(response.body) as Map<String, dynamic>;
    ...
  } else {
    // Error
  }
}

LocalStorageみたいなのを使いたい

shared_preferencesというパッケージを使う。

import 'package:shared_preferences/shared_preferences.dart';

Future sharedPreferences() {
  final Future<SharedPreferences> _prefs = SharedPreferences.getInstance();
  final SharedPreferences prefs = await _prefs;
  
  // get from shared preferences
  String hoge = prefs.getString('hoge');
  
  // set to shared preferences
  await prefs.setString('hoge', hoge);
}

画面遷移をしたい

Fultter標準のNavigator.pushを使う。

ElevatedButton(
  onPressed: () => {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => const NextPageWidget()
      )
    )
  },
  child: const Text("navigator push")
)

画面遷移時にちょっと処理を書きたい

Fultter標準のRouteObserverを使う。
まずmain.dartに書いていきます。

main.dart
final RouteObserver<ModalRoute> routeObserver = RouteObserver<ModalRoute>();

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  runApp(const MyApp());
}

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

  
  Widget build(BuildContext context) {
    return MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'App Title',
        theme: ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: const FreeePage(title: 'App Title'),
        navigatorObservers: [routeObserver]); // <- これを追加
  }
}

他のWidgetでこう書きます。

other.dart
class OtherWidget extends StatefulWidget {
  const OtherWidget({super.key});

  
  State<OtherWidget> createState() => OtherWidgetState();
}

class OtherWidgetState extends State<OtherWidget> with RouteAware {

  
  void didChangeDependencies() {
    super.didChangeDependencies();
    routeObserver.subscribe(this, ModalRoute.of(context)!);
  }

  
  void dispose() {
    routeObserver.unsubscribe(this);
    super.dispose();
  }

  
  void didPush() {
    // 画面が初めて表示 (Push) される時にコールされます。
  }

  
  void didPop() {
    // この画面から別の画面に遷移する (Pop) 場合にコールされます。
  }

  
  void didPushNext() {
    // この画面から別の画面をPushする場合にコールされます (この画面はPopされずにそのまま残る場合)。
  }

  
  void didPopNext() {
    // 一度、別の画面に遷移したあとで、再度この画面に戻ってきた時にコールされます。
  }

  
  Widget build(BuildContext context) => Container();
}

floatingActionButtonでメニューを開く感じにしたい

flutter_speed_dialというパッケージを使う。
こんなメニューを作ることができます。

floatingActionButton: SpeedDial(
  icon: Icons.settings,
  activeIcon: Icons.close,
  childPadding: const EdgeInsets.all(5),
  spaceBetweenChildren: 4,
  backgroundColor: Colors.grey[600],
  children: [
    SpeedDialChild(
      child: const Icon(Icons.cached),
      label: "更新",
      onTap: () => apiWrapper(
      WrappedAPIObject(function: getAvailableTypes)),
      foregroundColor: Colors.grey[800],
      labelStyle: TextStyle(color: Colors.grey[800])),
    SpeedDialChild(
      child: const Icon(Icons.person),
      label: "ユーザー情報",
      onTap: () => {
        setState(() {
          _isNeedRetry = true;
        }),
        Navigator.push(
          context,
          MaterialPageRoute(
            builder: (context) => const UserInfoPage()))
      },
      foregroundColor: Colors.grey[800],
      labelStyle: TextStyle(color: Colors.grey[800]))
  ]),

ローディング中UIを入れたい

Opacityというコンポーネントを使って、Overlayを作ります。
書く場所はStackのchildrenで返しているScaffoldと同じ階層


Widget build(BuildContext context) {
  return Stack(
    children: [
      Scaffold(...),
      const Opacity(
        opacity: 0.8,
        child: ModalBarrier(dismissible: false, color: Colors.black),
      ),
    ]
  )
}

CircularProgressIndicatorという関数を呼び出して、ぐるぐる回るコンポーネントを作ります。


Widget build(BuildContext context) {
  return Stack(
    children: [
      Scaffold(...),
      const Opacity(
        opacity: 0.8,
        child: ModalBarrier(dismissible: false, color: Colors.black),
      ),
      const Center(
	child: CircularProgressIndicator(),
      ),
    ],
  );
}

ローディングUI完成。

日付を扱いたい

Fultter標準のDateTimeとintlというパッケージを使う。

// 今の時間
DateTime now = DateTime.now();
// 時間を指定する(2020年10月7日12時34分)
DateTime a = DateTime(2022, 10, 7, 12, 34);
// Datetime型を決まった形式にフォーマットする
final formatter = DateFormat('yyyy-MM-dd');
String targetDate = formatter.format(now);

(デスクトップアプリ)ウィンドウサイズを定義したい

desktop_windowというパッケージを使う。
main.dartのmain関数内に書く。
setMinWindowSizesetMaxWindowSizeで同じ値を持たせることで大きさを固定することができます。

import 'package:desktop_window/desktop_window.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();

  await DesktopWindow.setWindowSize(const Size(450, 600));
  await DesktopWindow.setMinWindowSize(const Size(450, 600));
  await DesktopWindow.setMaxWindowSize(const Size(600, 800));

  runApp(const MyApp());
}

Discussion