..

押すだけタイマー をつくる(4)

presetに名称を付けられるようにしよう。

まず、Presetにプロパティを追加する。変更可能なプロパティを追加したので、コンストラクタのconstは削除する必要がある。
preset.dart

class Preset {
  Preset(this.id);
  final String id;
  String title = '';
}

つぎに、コントローラーにpresetを取得するための関数を追加する。該当idのpresetが存在しない場合は、新しいPresetを返却する。
preset_controller.dart

  Preset getPreset(String id) {
    var preset = _presets[id];
    if (preset != null) {
      return preset;
    }
    return Preset(id);
  }

準備はできたので、いよいよ入力欄を追加する。まず、build関数内で、Presetを生成していたのを上記getPreset関数で取得するように変更する。
preset_details_view.dart

Preset preset = controller.getPreset(itemid);

つづけて、入力値を扱うためのTextEditingControllerを用意する。初期値には、presetのtitleをつかう。

var titleController = TextEditingController(text: preset.title);

入力欄を追加し、追加ボタンが押されたときに、その入力値でpresetのtitleを更新するようにする。

children: [
  TextField(
    controller: titleController,
    maxLength: 30,
    decoration: InputDecoration(
      hintText: AppLocalizations.of(context)!.titleHint,
    ),
  ),
  ElevatedButton(
    onPressed: () {
      preset.title = titleController.text;
      controller.updatePreset(preset);
      Navigator.of(context).pop();
    },

app_en.arbとapp_ja.arbに、titleHintでつかう文字列を追加しておく。


つぎは時間の入力だが、flutter_pickerというプラグインをつかおう。

flutter_picker

Installingにあるように、pubspec.yamlに追記してpub getすると、なぜか、多言語対応のプラグインが見つからなくなった。

Target of URI doesn't exist: 'package:flutter_gen/gen_l10n/app_localizations.dart'.
The values in a const list literal must be constants.
Undefined name 'AppLocalizations'.

このエラーは、以下の記事にあるように、Dart Analysis Severを再起動すると解消された。

Target of URI doesn’t exist: …

うむ、よくわからない。

まず、Presetに分(minutes)と秒(seconds)のプロパティを追加する。 つぎに、PresetDetailsViewに、分と秒を表示する。そして、ここをタッチするとflutter_pickerをつかった入力画面表示できるようにする。

GestureDetector(
  onTap: () => showPickerNumber(context, preset),
  child: Row(
    mainAxisSize: MainAxisSize.min,
    children: [
      Text(
        preset.minutes.toString().padLeft(2, '0'),
        style: Theme.of(context).textTheme.headline2,
      ),
      Text(
        ':',
        style: Theme.of(context).textTheme.headline2,
      ),
      Text(
        preset.seconds.toString().padLeft(2, '0'),
        style: Theme.of(context).textTheme.headline2,
      ),
    ],
  ),
),

それから、flutter_pickerのサンプルを元に、showPickerNumber関数を追加しておく。分を99まで入力したいので、数値を選択できるサンプルを流用した。

showPickerNumber(BuildContext context, Preset preset) {
  Picker(
    adapter: NumberPickerAdapter(data: [
      NumberPickerColumn(begin: 0, end: 99, initValue: preset.minutes),
      NumberPickerColumn(begin: 0, end: 59, initValue: preset.seconds),
    ]),
    delimiter: [
      PickerDelimiter(
        child: Container(
          width: 30.0,
          alignment: Alignment.center,
          child: Icon(Icons.more_vert),
        ),
      )
    ],
    hideHeader: true,
    title: Text(AppLocalizations.of(context)!.selectTime),
    onConfirm: (Picker picker, List value) {
      preset.setMinutes(value[0]);
      preset.setSeconds(value[1]);
    },
  ).showDialog(context);
}

あとは、多言語対応。
app_en.arbとapp_ja.arbに、selectTimeでつかう文字列を追加しておく。 flutter_picker自体も多言語対応しているので、app.dartにも以下のように追記しておく。

localizationsDelegates: const [
 AppLocalizations.delegate,
 GlobalMaterialLocalizations.delegate,
 GlobalWidgetsLocalizations.delegate,
 GlobalCupertinoLocalizations.delegate,
 PickerLocalizationsDelegate.delegate, // 追加した
],

これで、分と秒も設定できるようになった。ただし、詳細画面ではリロードしないと反映されない。