PR

[Flutter]Flutter Widget of the Week「#145 firebase_crashlytics」、「#146 Draggable(Take 2)」、「#147 CallbackShortcuts」

Flutter

はじめに

前回はFlutter Widget of the Weekの「#142 flutter_lints」、「#143 firebase_storage」、「#144 flutter_animate」を紹介しました。

今回はその続きで「#145 firebase_crashlytics」、「#146 Draggable(Take 2)」、「#147 CallbackShortcuts」の3つです。

前回の記事はこちら

またGitHubにも公開しています。

GitHub - nobushiueshi/flutter_widget_of_the_week
Contribute to nobushiueshi/flutter_widget_of_the_week development by creating an account on GitHub.

Flutter Widget of the Week

環境

  • Flutter 3.19.6

記事にした時点でのバージョンです。GitHubに公開しているのは常に最新の安定版(stable)を使う予定です。

#145 firebase_crashlytics

firebase_crashlyticsとは?

軽量・リアルタイムのクラッシュレポート機能を提供しているFirebase Crashlyticsというサービスのパッケージです。

サンプルコード

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // Firebase.
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  // Firebase Crashlytics.
  FlutterError.onError = (errorDetails) {
    FirebaseCrashlytics.instance.recordFlutterFatalError(errorDetails);
  };
  // Pass all uncaught asynchronous errors that aren't handled by the Flutter
  // framework to Crashlytics
  PlatformDispatcher.instance.onError = (error, stack) {
    FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
    return true;
  };

  runApp(const MyApp());
}
import 'package:flutter/material.dart';

class SamplePage145 extends StatefulWidget {
  const SamplePage145({
    super.key,
  });

  @override
  State<SamplePage145> createState() => _SamplePage145State();
}

class _SamplePage145State extends State<SamplePage145> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('firebase_crashlytics'),
        centerTitle: true,
      ),
      body: SafeArea(
        child: Center(
          child: FilledButton.icon(
            label: const Text('Force Crash'),
            icon: const Icon(Icons.error),
            onPressed: () {
              throw Exception();
            },
          ),
        ),
      ),
    );
  }
}

結果

画面のボタンを押し、クラッシュを発生させます。

Visual Studio Code上でもクラッシュしたのがわかると思います。

Firebase Crashlyticsを見るとクラッシュのレポートが表示されているのがわかります。

動画

公式リファレンス

firebase_crashlytics | Flutter package
Flutter plugin for Firebase Crashlytics. It reports uncaught errors to the Firebase console.

#146 Draggable(Take 2)

Draggable(Take 2)とは?

ドラッグアンドドロップを実現できるウィジェットです。なぜか2回目の登場です。

前回の記事はこちら

サンプルコード

import 'package:flutter/material.dart';

class SamplePage146 extends StatefulWidget {
  const SamplePage146({
    super.key,
  });

  @override
  State<SamplePage146> createState() => _SamplePage146State();
}

class _SamplePage146State extends State<SamplePage146> {
  Color _selectedColor = Colors.white;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Draggable(Take 2)'),
        centerTitle: true,
      ),
      body: SafeArea(
        child: Column(
          children: [
            Container(
              width: double.infinity,
              height: 120,
              color: Colors.grey[100],
              child: const Row(
                mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                children: [
                  _SamplePage146Draggable(
                    color: Colors.blue,
                  ),
                  _SamplePage146Draggable(
                    color: Colors.yellow,
                  ),
                  _SamplePage146Draggable(
                    color: Colors.red,
                  ),
                ],
              ),
            ),
            Expanded(
              child: ColoredBox(
                color: _selectedColor,
                child: Center(
                  child: DragTarget<Color>(
                    onWillAcceptWithDetails: (value) =>
                        value.data != _selectedColor,
                    onAcceptWithDetails: (value) {
                      setState(() {
                        _selectedColor = value.data;
                      });
                    },
                    builder: (context, candidates, rejects) {
                      return Container(
                        width: 100,
                        height: 100,
                        decoration: BoxDecoration(
                          border: Border.all(),
                          color: Colors.white,
                        ),
                        child: const Center(
                          child: Text('ここに\nドラッグ'),
                        ),
                      );
                    },
                  ),
                ),
              ),
            ),
          ],
        ),
      ),
    );
  }
}

class _SamplePage146Draggable extends StatelessWidget {
  const _SamplePage146Draggable({
    this.color,
  });

  final Color? color;

  @override
  Widget build(BuildContext context) {
    return Draggable<Color>(
      data: color,
      childWhenDragging: _SamplePage146Child(
        color: color,
        child: const Text('ドラッグ中'),
      ),
      feedback: _SamplePage146Child(
        color: color,
        child: const Icon(Icons.face),
      ),
      child: _SamplePage146Child(
        color: color,
        child: const Text('通常'),
      ),
    );
  }
}

class _SamplePage146Child extends StatelessWidget {
  const _SamplePage146Child({
    this.color,
    this.child,
  });

  final Color? color;
  final Widget? child;

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 100,
      height: 100,
      color: color,
      child: Center(child: child),
    );
  }
}

結果

結果は前回と全く一緒なので割愛します。

動画

公式リファレンス

Draggable class - widgets library - Dart API
API docs for the Draggable class from the widgets library, for the Dart programming language.

#147 CallbackShortcuts

CallbackShortcutsとは?

キーボードのショートカットを追加できるWidgetです。

Shortcuts/Actions/Intentsと違い、キーボードバインディングをコールバックに直接マッピングできるのでActionsやIntentsが不要なので実装しやすいです。

ただし、より高度な実装にはShortcutsのほうが適しています。

サンプルコード

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

class SamplePage147 extends StatefulWidget {
  const SamplePage147({
    super.key,
  });

  @override
  State<SamplePage147> createState() => _SamplePage147State();
}

class _SamplePage147State extends State<SamplePage147> {
  int count = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('CallbackShortcuts'),
        centerTitle: true,
      ),
      body: SafeArea(
        child: Center(
          child: CallbackShortcuts(
            bindings: <ShortcutActivator, VoidCallback>{
              const SingleActivator(LogicalKeyboardKey.keyU, control: true):
                  () {
                setState(() {
                  count = count + 1;
                });
              },
              const SingleActivator(LogicalKeyboardKey.keyD, control: true):
                  () {
                setState(() {
                  count = count - 1;
                });
              },
            },
            child: Focus(
              autofocus: true,
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: [
                  Text('count: $count'),
                  const SizedBox(height: 40),
                  const Text('ここにフォーカスがある時にCtrl + Uでカウントアップ'),
                  const Text('ここにフォーカスがある時にCtrl + Dでカウントダウン'),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

結果

Ctrl + D、Ctrl + Uで簡単に操作ができるようになりました。

動画

公式リファレンス

CallbackShortcuts class - widgets library - Dart API
API docs for the CallbackShortcuts class from the widgets library, for the Dart programming language.

さいごに

サボってしまった。。。

おすすめ参考書

リンク

GitHub - nobushiueshi/flutter_widget_of_the_week
Contribute to nobushiueshi/flutter_widget_of_the_week development by creating an account on GitHub.

コメント

タイトルとURLをコピーしました