FIX keyboard
This commit is contained in:
127
lib/main.dart
127
lib/main.dart
@@ -307,17 +307,20 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
return _formatDuration(duration);
|
return _formatDuration(duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update keyboard handler method to use modern KeyEvent API
|
||||||
void _handleKeyEvent(KeyEvent event) {
|
void _handleKeyEvent(KeyEvent event) {
|
||||||
|
// Only process key down events to avoid duplicate triggers
|
||||||
if (event is KeyDownEvent) {
|
if (event is KeyDownEvent) {
|
||||||
|
// Handle Space key
|
||||||
if (event.logicalKey == LogicalKeyboardKey.space) {
|
if (event.logicalKey == LogicalKeyboardKey.space) {
|
||||||
// Space: Start if paused, Lap if running
|
|
||||||
if (_isRunning) {
|
if (_isRunning) {
|
||||||
_recordLap();
|
_recordLap();
|
||||||
} else {
|
} else {
|
||||||
_startTimer();
|
_startTimer();
|
||||||
}
|
}
|
||||||
} else if (event.logicalKey == LogicalKeyboardKey.enter) {
|
}
|
||||||
// Enter: Stop if paused, Pause if running
|
// Handle Enter key
|
||||||
|
else if (event.logicalKey == LogicalKeyboardKey.enter) {
|
||||||
if (_isRunning) {
|
if (_isRunning) {
|
||||||
_pauseTimer();
|
_pauseTimer();
|
||||||
} else {
|
} else {
|
||||||
@@ -336,74 +339,84 @@ class _MyHomePageState extends State<MyHomePage> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return KeyboardListener(
|
// Use Focus directly to capture key events
|
||||||
|
return Focus(
|
||||||
focusNode: _focusNode,
|
focusNode: _focusNode,
|
||||||
onKeyEvent: _handleKeyEvent,
|
|
||||||
autofocus: true,
|
autofocus: true,
|
||||||
|
onKeyEvent: (FocusNode node, KeyEvent event) {
|
||||||
|
_handleKeyEvent(event);
|
||||||
|
// Always return KeyEventResult.handled to indicate we've processed the event
|
||||||
|
return KeyEventResult.handled;
|
||||||
|
},
|
||||||
child: Scaffold(
|
child: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
|
||||||
title: Text(widget.title),
|
title: Text(widget.title),
|
||||||
),
|
),
|
||||||
body: Center(
|
body: GestureDetector(
|
||||||
child: Column(
|
// This ensures tapping anywhere gives focus back to our listener
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
onTap: () => _focusNode.requestFocus(),
|
||||||
children: [
|
behavior: HitTestBehavior.translucent,
|
||||||
const SizedBox(height: 10),
|
child: Center(
|
||||||
// Use a fixed height container to prevent expanding and force horizontal scrolling if needed
|
child: Column(
|
||||||
SizedBox(
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
height: 50,
|
children: [
|
||||||
child: SingleChildScrollView(
|
const SizedBox(height: 10),
|
||||||
scrollDirection: Axis.horizontal,
|
// Use a fixed height container to prevent expanding and force horizontal scrolling if needed
|
||||||
child: Text(
|
SizedBox(
|
||||||
_formatDuration(_elapsedTime),
|
height: 50,
|
||||||
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
|
child: SingleChildScrollView(
|
||||||
fontFamily: 'monospace', // Use monospaced font for fixed-width characters
|
scrollDirection: Axis.horizontal,
|
||||||
|
child: Text(
|
||||||
|
_formatDuration(_elapsedTime),
|
||||||
|
style: Theme.of(context).textTheme.headlineMedium?.copyWith(
|
||||||
|
fontFamily: 'monospace', // Use monospaced font for fixed-width characters
|
||||||
|
),
|
||||||
|
softWrap: false, // Prevent text wrapping
|
||||||
|
overflow: TextOverflow.visible, // Allow text to extend beyond bounds
|
||||||
),
|
),
|
||||||
softWrap: false, // Prevent text wrapping
|
|
||||||
overflow: TextOverflow.visible, // Allow text to extend beyond bounds
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(height: 30),
|
||||||
const SizedBox(height: 30),
|
Row(
|
||||||
Row(
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
children: [
|
||||||
children: [
|
ElevatedButton(
|
||||||
ElevatedButton(
|
onPressed: _isRunning ? _pauseTimer : _startTimer,
|
||||||
onPressed: _isRunning ? _pauseTimer : _startTimer,
|
child: Text(_isRunning ? 'Pause' : 'Start'),
|
||||||
child: Text(_isRunning ? 'Pause' : 'Start'),
|
),
|
||||||
|
const SizedBox(width: 20),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: _stopTimer,
|
||||||
|
child: const Text('Stop'),
|
||||||
|
),
|
||||||
|
const SizedBox(width: 20),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: _recordLap,
|
||||||
|
child: const Text('Lap'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
if (_laps.isNotEmpty) ...[
|
||||||
|
Text(
|
||||||
|
'Laps:',
|
||||||
|
style: Theme.of(context).textTheme.titleLarge,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 20),
|
const SizedBox(height: 10),
|
||||||
ElevatedButton(
|
Expanded(
|
||||||
onPressed: _stopTimer,
|
child: ListView.builder(
|
||||||
child: const Text('Stop'),
|
itemCount: _laps.length,
|
||||||
),
|
itemBuilder: (context, index) {
|
||||||
const SizedBox(width: 20),
|
return ListTile(
|
||||||
ElevatedButton(
|
title: Text('Lap ${index + 1}: ${_laps[index]}'),
|
||||||
onPressed: _recordLap,
|
);
|
||||||
child: const Text('Lap'),
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
|
||||||
const SizedBox(height: 20),
|
|
||||||
if (_laps.isNotEmpty) ...[
|
|
||||||
Text(
|
|
||||||
'Laps:',
|
|
||||||
style: Theme.of(context).textTheme.titleLarge,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 10),
|
|
||||||
Expanded(
|
|
||||||
child: ListView.builder(
|
|
||||||
itemCount: _laps.length,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
return ListTile(
|
|
||||||
title: Text('Lap ${index + 1}: ${_laps[index]}'),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Reference in New Issue
Block a user