このようなラジオボタン入りのリストを作成してみたかったのですが、RadioListTile
ウィジェットを利用すると高さに限界値があってスリムにスタイル良くいきませんでした。
これ以上は狭めれないのです。これで問題なければ、下記↓実装でいいと思います。
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('選択肢1',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.black87,
),
),
value: RadioValue.FIRST,
groupValue: _gValue,
onChanged: (value) => _onRadioSelected(value),
),
),
),
Card(
child: RadioListTile(
title: text('選択肢2', 16),
value: RadioValue.SECOND,
groupValue: _gValue,
onChanged: (value) => _onRadioSelected(value),
),
),
Card(
child: RadioListTile(
title: text('選択肢3', 16),
value: RadioValue.THIRD,
groupValue: _gValue,
onChanged: (value) => _onRadioSelected(value),
),
),
],
),
),
ただ、スクロールせずにスッキリとまとめるにはやはりこの方が見栄えがいいかと、そこで下記ウィジェットを作成しました。
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
が以下になります。
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>(
'選択肢1',
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>(
'選択肢2',
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>(
'選択肢3',
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
を使って状態管理をしてあげれば完成です。
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));
// }
}