Freezedを使ってラジオボタン付きリストを作成

![スクリーンショット 2022-07-25 14.48.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/2be99f40-e573-160a-87a9-90ed8d564e6c.png)
このようなラジオボタン入りのリストを作成してみたかったのですが、`RadioListTile`ウィジェットを利用すると高さに限界値があってスリムにスタイル良くいきませんでした。
![スクリーンショット 2022-07-25 15.06.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/f05d9396-fd0c-eb4d-f43f-69bcb4c8287a.png)
これ以上は狭めれないのです。これで問題なければ、下記↓実装でいいと思います。
```dart
Container(
          width: double.infinity,
          height: 40.0,
          child: textGrey('Radio List', 15),
          padding: const EdgeInsets.only(top: 15.0, left: 15.0)
),
SafeArea(
         child: Column(
         children: [
           Card(
           child: Container(
           child: RadioListTile(
           title: Text('選択肢１',
             style: TextStyle(
               fontSize: 16,
               fontWeight: FontWeight.bold,
               color: Colors.black87,
                       ),
               ),
               value: RadioValue.FIRST,
               groupValue: _gValue,
               onChanged: (value) => _onRadioSelected(value),
              ),
            ),
          ),
          Card(
          child: RadioListTile(
          title: text('選択肢２', 16),
          value: RadioValue.SECOND,
          groupValue: _gValue,
          onChanged: (value) => _onRadioSelected(value),
            ),
          ),
          Card(
          child: RadioListTile(
          title: text('選択肢３', 16),
          value: RadioValue.THIRD,
          groupValue: _gValue,
          onChanged: (value) => _onRadioSelected(value),
            ),
          ),
        ],
      ),
),
```
![スクリーンショット 2022-07-25 15.22.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1134006/e322ca0b-08ee-0d29-a556-18b0b93a799c.png)
ただ、スクロールせずにスッキリとまとめるにはやはりこの方が見栄えがいいかと、そこで下記ウィジェットを作成しました。
```dart
Widget radioBox<T>(
  String label,
  Color color,
  T groupValue,
  T value,
  void Function(T?) onChange,
) {
  return Container(
      decoration: BoxDecoration(
        boxShadow: [
          BoxShadow(
            color: Colors.grey.withOpacity(0.5),
            spreadRadius: 0.2,
            blurRadius: 0.5,
            offset: Offset(0.1, 0.7),
          ),
        ],
        borderRadius: BorderRadius.circular(3),
        color: Colors.white,
      ),
      width: 367,
      height: 40,
      child: Container(
          child: Row(mainAxisAlignment: MainAxisAlignment.start, children: [
        SizedBox(
          width: 10,
        ),
        new Radio<T>(
          activeColor: color,
          groupValue: groupValue,
          value: value,
          onChanged: onChange,
        ),
        SizedBox(
          width: 15,
        ),
        text(label, 16)
      ])));
}
```
この作成した`radioBox`ウィジェットを利用した`UI`が以下になります。
```dart
enum RadioList { OptionA, OptionB, OptionC }

// build内
Container(
  width: double.infinity,
  height: 40.0,
  child: textGrey('Radio List', 15),
  padding: const EdgeInsets.only(top: 15.0, left: 15.0)
),
                      
radioBox<radioList>(
  '選択肢１',
  Colors.blue,
  provider.Provider.of<AppDetailState>(
    context, listen: true
  ).setting.radioList,
  radioList.OptionA, (val) {
    provider.Provider.of<AppStateNotifier>(
      context, listen: false
    ).updateRadioList(val!);
     
    }),
SizedBox(height: 2),
radioBox<radioList>(
  '選択肢２',
  Colors.blue,
  provider.Provider.of<AppDetailState>(
    context, listen: true
  ).setting.radioList,
  radioList.OptionB, (val) {
    provider.Provider.of<AppStateNotifier>(
      context, listen: false
    ).updateRadioList(val!);
     
    }),
SizedBox(height: 2),
radioBox<radioList>(
  '選択肢３',
  Colors.blue,
  provider.Provider.of<AppDetailState>(
    context, listen: true
  ).setting.radioList,
  radioList.OptionC, (val) {
    provider.Provider.of<AppStateNotifier>(
      context, listen: false
    ).updateRadioList(val!); 
     
    }),
SizedBox(height: 2),
```

あとは、`Provider`を使って状態管理をしてあげれば完成です。
```dart
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import '../models/setting.dart';
import '../models/user.dart';

part 'app_state.freezed.dart';

@freezed
class AppState with _$AppState {
  const factory AppState(Setting setting) = AppDetailState;
}
class AppStateNotifier extends StateNotifier<AppDetailState> {
  AppStateNotifier(Setting setting)
      : super(AppDetailState(setting)) {}

  static Future<AppStateNotifier> async {
    final setting = await settingsService.fetchSetting();
  return AppStateNotifier(setting);
  }

//　（メソッド例）
// radioList(radioList v) async {
//    final prefs = await SharedPreferences.getInstance();
//    await prefs.setString("radioList", v.name);
//    state = state.copyWith(setting: state.setting.copyWith(radioList: v));
//  }
}