openHourMinutePickerPopupLive function
Future<void>
openHourMinutePickerPopupLive({
- required BuildContext context,
- required HourMinute initialValue,
- HourMinute? minValue,
- HourMinute? maxValue,
- required void onChanged(
- HourMinute newValue
HourMinute ピッカーをポップアップメニューとして表示する
context - 表示するコンテキスト(通常はボタンのcontext)
initialValue - 初期値
minValue - 最小値(オプション)
maxValue - 最大値(オプション)
onChanged - 値が変更されたときのコールバック(ホイールのスクロールが止まったときに呼ばれる)
戻り値: ポップアップが閉じられるまで待機するFuture
Implementation
Future<void> openHourMinutePickerPopupLive({
required BuildContext context,
required HourMinute initialValue,
HourMinute? minValue,
HourMinute? maxValue,
required void Function(HourMinute newValue) onChanged,
}) {
final RenderBox button = context.findRenderObject() as RenderBox;
final RenderBox overlay =
Overlay.of(context).context.findRenderObject() as RenderBox;
final Offset position = button.localToGlobal(Offset.zero, ancestor: overlay);
final Size screenSize = MediaQuery.of(context).size;
const double margin = 16.0;
const double menuWidth = 300.0;
// 画面端からの余白を考慮した位置調整
double left = position.dx;
double right = screenSize.width - position.dx - button.size.width;
// 右端に近すぎる場合は左に寄せる
if (left + menuWidth > screenSize.width - margin) {
left = screenSize.width - menuWidth - margin;
right = margin;
}
// 左端に近すぎる場合は右に寄せる
if (left < margin) {
left = margin;
right = screenSize.width - menuWidth - margin;
}
return showMenu<void>(
context: context,
color: Colors.white,
surfaceTintColor: Colors.transparent,
elevation: 8,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
position: RelativeRect.fromLTRB(
left,
position.dy + button.size.height + 8,
right,
screenSize.height - position.dy - button.size.height - margin,
),
items: [
PopupMenuItem<void>(
enabled: false,
padding: EdgeInsets.zero,
child: SizedBox(
width: menuWidth,
child: _HourMinutePickerPopupLiveContent(
initialValue: initialValue,
minValue: minValue,
maxValue: maxValue,
onChanged: onChanged,
onComplete: () {
Navigator.pop(context);
},
),
),
),
],
);
}