2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Zapp!でニフクラ mobile backendのデモ(Todoアプリ)を体験できます

Posted at

Zapp!はFlutterアプリをクラウド環境で開発できるサービスです。DartPadと違って、任意のFlutter/Dartパッケージをインストールできます。

image.png

そんなZapp!を使って、ニフクラ mobile backendのFlutter SDKを利用したデモアプリであるTodoアプリを体験できるようにしました。

アプリの概要

アプリは2画面で作られています。

Todo一覧画面

0123 zt006jut106.zapp.page - 0922143642.jpg

NCMBのデータストアからTodoを一覧取得、画面に表示します。

Todo編集画面

0123 zt006jut106.zapp.page - 0922143645.jpg

一覧画面でタップされたTodoを編集する画面です。新規登録でも同じ画面を使っています。

アプリの機能

データストアのCRUD操作(データの取得、新規作成、更新、削除)が体験できます。タスクのスワイプで削除が出ます。

0123 zt006jut106.zapp.page - 0922143647.jpg

データは自由に操作してもらって構いません。

アプリのURL

Todoアプリは下記のURLで試せます。

アプリのコード

アプリのコードは下記になります。

Zapp!は誰でも編集できるような気がするので、こちらに予備としてコードを全文残しておきます。

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

void main() {
  // NCMBを初期化
  NCMB('9170ffcb91da1bbe0eff808a967e12ce081ae9e3262ad3e5c3cac0d9e54ad941', '9e5014cd2d76a73b4596deffdc6ec4028cfc1373529325f8e71b7a6ed553157d');
  // 最初に表示するWidget
  runApp(MyTodoApp());
}

class MyTodoApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      // 右上に表示される"debug"ラベルを消す
      debugShowCheckedModeBanner: false,
      // アプリ名
      title: 'タスクアプリ',
      theme: ThemeData(
        // テーマカラー
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      // リスト一覧画面を表示
      home: TodoListPage(),
    );
  }
}

// タスク一覧画面用Widget
class TodoListPage extends StatefulWidget {
  @override
  _TodoListPageState createState() => _TodoListPageState();
}

// タスク一覧画面用ステート
class _TodoListPageState extends State<TodoListPage> {
  // Todoリストのデータ(初期値は空)
  List<NCMBObject> todoList = [];

  // 初期データをセットアップする処理
  @override
  void initState() {
    super.initState();
    getAllTask();
  }

  // NCMBから既存のTodoリストを取得する処理
  void getAllTask() async {
    // Todoクラス(DBで言うテーブル相当)を検索するクエリーオブジェクト
    var query = NCMBQuery('Todo');
    // データを取得
    var items = await query.fetchAll();
    // データを適用
    setState(() {
      todoList = items
        .map((item) => item as NCMBObject)
        .toList();
    });
  }

  // 画面構築
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // 画面上部に表示するAppBar
      appBar: AppBar(
        title: Text('タスク一覧'),
        // タスク追加用のアイコンを設置
        actions: <Widget>[
          IconButton(
            icon: Icon(Icons.add),
            onPressed: () async {
              // 新しいTodoを取得
              final NCMBObject item = await Navigator.of(context).push(
                MaterialPageRoute(builder: (context) {
                  // タスクの追加、編集を行う画面への遷移
                  return TodoPage(
                    // 初期値としてNCMBObjectを渡す
                    todo: NCMBObject('Todo'),
                  );
                }),
              );
              // レスポンスがあれば、リストに追加
              // キャンセルされた場合は null が来る
              if (item != null) {
                setState(() {
                  todoList.add(item);
                });
              }
            },
          ),
        ],
      ),
      // データを元にListViewを作成
      body: ListView.builder(
        itemCount: todoList.length,
        itemBuilder: (context, index) {
          final item = todoList[index];
          // スワイプで削除する機能
          return Dismissible(
            key: Key(item.get('objectId') as String),
            child: Card(
              child: ListTile(
                title: Text(item.get('body') as String),
                onTap: () async {
                  // タップした際には編集画面に遷移する
                  final NCMBObject obj = await Navigator.of(context).push(
                    MaterialPageRoute(builder: (context) {
                      return TodoPage(
                        todo: item,
                      );
                    }),
                  );
                  // 編集後のデータがあれば、リストを更新する
                  if (obj != null) {
                    setState(() {
                      todoList[index] = obj;
                    });
                  }
                },
              ),
            ),
            direction: DismissDirection.endToStart,
            // スワイプした際に表示する削除ラベル
            background: new Container(
                padding: EdgeInsets.only(right: 20.0),
                color: Colors.red.shade500,
                child: new Align(
                  alignment: Alignment.centerRight,
                  child: new Text('削除',
                      textAlign: TextAlign.right,
                      style: new TextStyle(color: Colors.white)),
                )),
            // スワイプした際に処理
            onDismissed: (direction) {
              // スワイプされた要素をデータから削除する
              setState(() {
                todoList[index].delete();
                todoList.removeAt(index);
              });
              // Snackbarを表示する
              ScaffoldMessenger.of(context)
                  .showSnackBar(SnackBar(content: Text('削除しました')));
            },
          );
        },
      ),
    );
  }
}

// Todoを受け取るステートフルウィジェット
class TodoPage extends StatefulWidget {
  TodoPage({
    Key? key,
    required this.todo,
  }) : super(key: key);

  final NCMBObject todo;

  @override
  _TodoPageState createState() => _TodoPageState();
}

// Todoの追加、または更新を行うウィジェット
class _TodoPageState extends State<TodoPage> {
  // テキスト入力用
  String? _text;
  @override
  Widget build(BuildContext context) {
    // 画面表示用のラベル
    final label = widget.todo.get('objectId') != null ? 'リスト更新' : 'リスト追加';
    return Scaffold(
      // 画面上部に表示するAppBar
      appBar: AppBar(
        title: Text(label),
        actions: <Widget>[
          // 新規保存、更新用のボタン
          IconButton(
            icon: Icon(Icons.save),
            onPressed: () async {
              // 保存処理
              widget.todo.set('body', _text!);
              await widget.todo.save();
              // 前の画面に戻る
              Navigator.of(context).pop(widget.todo);
            },
          ),
        ],
      ),
      body: Container(
        // 余白を付ける
        padding: EdgeInsets.all(64),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const SizedBox(height: 8),
            // テキスト入力
            TextFormField(
              // 初期値の設定。デフォルト値は空文字
              initialValue: (_text = widget.todo.getString('body', defaultValue: "")),
              onChanged: (String value) {
                _text = value;
              },
            ),
          ],
        ),
      ),
    );
  }
}

コードの解説

このTodoアプリは【ハンズオン資料】NCMBのFlutter SDKを使ってTodoアプリを作る - Qiitaのコードを利用しています。Flutter 3.0.5に合わせて多少の修正が入っています。

まとめ

FlutterアプリでNCMBを使う際の参考として、ぜひご覧ください。データストアの基本的な使い方が分かるはずです。

mBaaSでサーバー開発不要! | ニフクラ mobile backend

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?