main, fix older versions of Android not being able to see bottom widgets when keyboard is open.

This commit is contained in:
me committed 2026-09-28 09:07:22 -07:00
1 parent f5e368a902
commit 7ab13dd4de
1 file changed
+169 -166
+169 -166
View File
@@ -368,183 +368,186 @@ class _HomeScreenState extends State<HomeScreen> {
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Sunset Alarm')),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// --- Location section ---
const Text(
'Location',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
Row(
children: [
Expanded(
child: TextField(
controller: _latController,
keyboardType: const TextInputType.numberWithOptions(
signed: true,
decimal: true,
),
decoration: const InputDecoration(
labelText: 'Latitude',
border: OutlineInputBorder(),
),
onChanged: (_) => _savePrefs(),
),
),
const SizedBox(width: 8),
Expanded(
child: TextField(
controller: _lngController,
keyboardType: const TextInputType.numberWithOptions(
signed: true,
decimal: true,
),
decoration: const InputDecoration(
labelText: 'Longitude',
border: OutlineInputBorder(),
),
onChanged: (_) => _savePrefs(),
),
),
const SizedBox(width: 8),
IconButton.filledTonal(
icon: const Icon(Icons.my_location),
tooltip: 'Get GPS Location',
onPressed: _getGpsLocation,
),
],
),
const SizedBox(height: 16),
// --- Sunset time section ---
const Text(
'Sunset',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
Row(
children: [
Expanded(
child: TextField(
controller: _sunsetController,
decoration: InputDecoration(
labelText: 'Sunset Time (HH:MM)',
border: OutlineInputBorder(),
errorText: _sunsetErrorText,
suffixIcon: IconButton(
icon: Icon(Icons.access_time),
onPressed: () async {
final picked = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
if (picked != null) {
_sunsetController.text =
'${picked.hour.toString().padLeft(2, '0')}:'
'${picked.minute.toString().padLeft(2, '0')}';
setState(
() =>
_sunsetErrorText = _validateTime(
_sunsetController.text,
),
);
if (_alarmEnabled) {
_scheduleAlarm();
}
}
},
),
),
onChanged: (v) {
final val = _validateTime(v);
if (val == null) {
_savePrefs();
if (_alarmEnabled) {
_scheduleAlarm();
}
}
setState(() {
_sunsetErrorText = val;
});
},
),
),
const SizedBox(width: 8),
IconButton.filledTonal(
icon:
_loading
? const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Icon(Icons.cloud_done_outlined),
tooltip: 'Fetch Open-Meteo Sunset Data',
onPressed: () {
if (!_loading) {
_fetchSunset();
}
},
),
],
),
const SizedBox(height: 16),
const Text(
'Alert',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
// --- Minutes before ---
Row(
children: [
if (!_alarmEnabled)
resizeToAvoidBottomInset: true, // default, but be explicit
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// --- Location section ---
const Text(
'Location',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
Row(
children: [
Expanded(
child: TextField(
controller: _minutesController,
keyboardType: TextInputType.number,
decoration: InputDecoration(
controller: _latController,
keyboardType: const TextInputType.numberWithOptions(
signed: true,
decimal: true,
),
decoration: const InputDecoration(
labelText: 'Latitude',
border: OutlineInputBorder(),
labelText: 'Minutes Before Sunset',
errorText: _minuteErrorText,
),
onChanged: (_) => _savePrefs(),
),
),
const SizedBox(width: 8),
Expanded(
child: TextField(
controller: _lngController,
keyboardType: const TextInputType.numberWithOptions(
signed: true,
decimal: true,
),
decoration: const InputDecoration(
labelText: 'Longitude',
border: OutlineInputBorder(),
),
onChanged: (_) => _savePrefs(),
),
),
const SizedBox(width: 8),
IconButton.filledTonal(
icon: const Icon(Icons.my_location),
tooltip: 'Get GPS Location',
onPressed: _getGpsLocation,
),
],
),
const SizedBox(height: 16),
// --- Sunset time section ---
const Text(
'Sunset',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
Row(
children: [
Expanded(
child: TextField(
controller: _sunsetController,
decoration: InputDecoration(
labelText: 'Sunset Time (HH:MM)',
border: OutlineInputBorder(),
errorText: _sunsetErrorText,
suffixIcon: IconButton(
icon: Icon(Icons.access_time),
onPressed: () async {
final picked = await showTimePicker(
context: context,
initialTime: TimeOfDay.now(),
);
if (picked != null) {
_sunsetController.text =
'${picked.hour.toString().padLeft(2, '0')}:'
'${picked.minute.toString().padLeft(2, '0')}';
setState(
() =>
_sunsetErrorText = _validateTime(
_sunsetController.text,
),
);
if (_alarmEnabled) {
_scheduleAlarm();
}
}
},
),
),
onChanged: (v) {
final val = int.tryParse(v);
setState(() {
if (val != null) {
_minuteErrorText = null;
_minutesBefore = val;
} else {
_minuteErrorText = 'Invalid Minute Value';
final val = _validateTime(v);
if (val == null) {
_savePrefs();
if (_alarmEnabled) {
_scheduleAlarm();
}
_plural = (_minutesBefore == 1) ? '' : 's';
}
setState(() {
_sunsetErrorText = val;
});
},
),
),
// --- Toggle ---
Expanded(
child: SwitchListTile(
//title: const Text('Enable Sunset Alarm'),
title: Text(_alarmEnabled ? 'Sunset Alarm Enabled' : ''),
subtitle: Text(
_alarmEnabled
? '${_minutesBefore} Minute${_plural} Before @ $_alarmDisplayTime'
: '',
),
value: _alarmEnabled,
onChanged: _toggleAlarm,
const SizedBox(width: 8),
IconButton.filledTonal(
icon:
_loading
? const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(strokeWidth: 2),
)
: const Icon(Icons.cloud_done_outlined),
tooltip: 'Fetch Open-Meteo Sunset Data',
onPressed: () {
if (!_loading) {
_fetchSunset();
}
},
),
),
],
),
],
],
),
const SizedBox(height: 16),
const Text(
'Alert',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
// --- Minutes before ---
Row(
children: [
if (!_alarmEnabled)
Expanded(
child: TextField(
controller: _minutesController,
keyboardType: TextInputType.number,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Minutes Before Sunset',
errorText: _minuteErrorText,
),
onChanged: (v) {
final val = int.tryParse(v);
setState(() {
if (val != null) {
_minuteErrorText = null;
_minutesBefore = val;
} else {
_minuteErrorText = 'Invalid Minute Value';
}
_plural = (_minutesBefore == 1) ? '' : 's';
});
},
),
),
// --- Toggle ---
Expanded(
child: SwitchListTile(
//title: const Text('Enable Sunset Alarm'),
title: Text(_alarmEnabled ? 'Sunset Alarm Enabled' : ''),
subtitle: Text(
_alarmEnabled
? '${_minutesBefore} Minute${_plural} Before @ $_alarmDisplayTime'
: '',
),
value: _alarmEnabled,
onChanged: _toggleAlarm,
),
),
],
),
],
),
),
),
);