Merge pull request #154 from gskinnerTeam/feature/keyboard-scrolling
Add fullscreen keyboard list scroller component
This commit is contained in:
commit
9045b5d8fd
75
lib/ui/common/fullscreen_keyboard_list_scroller.dart
Normal file
75
lib/ui/common/fullscreen_keyboard_list_scroller.dart
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import 'package:wonders/common_libs.dart';
|
||||||
|
import 'package:wonders/logic/common/throttler.dart';
|
||||||
|
import 'package:wonders/ui/common/fullscreen_keyboard_listener.dart';
|
||||||
|
|
||||||
|
class FullscreenKeyboardListScroller extends StatelessWidget {
|
||||||
|
FullscreenKeyboardListScroller({super.key, required this.child, required this.scrollController});
|
||||||
|
|
||||||
|
static const int _scrollAmountOnPress = 75;
|
||||||
|
static const int _scrollAmountOnHold = 30;
|
||||||
|
static final Duration _keyPressAnimationDuration = $styles.times.fast * .5;
|
||||||
|
|
||||||
|
final Widget child;
|
||||||
|
final ScrollController scrollController;
|
||||||
|
final Throttler _throttler = Throttler(32.milliseconds);
|
||||||
|
|
||||||
|
double clampOffset(px) => px.clamp(0, scrollController.position.maxScrollExtent).toDouble();
|
||||||
|
|
||||||
|
void _handleKeyDown(int px) {
|
||||||
|
scrollController.animateTo(
|
||||||
|
clampOffset(scrollController.offset + px),
|
||||||
|
duration: _keyPressAnimationDuration,
|
||||||
|
curve: Curves.easeOut,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleKeyRepeat(int px) {
|
||||||
|
final offset = clampOffset(scrollController.offset + px);
|
||||||
|
_throttler.call(() => scrollController.jumpTo(offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return FullscreenKeyboardListener(
|
||||||
|
child: child,
|
||||||
|
onKeyRepeat: (event) {
|
||||||
|
if (event.logicalKey == LogicalKeyboardKey.arrowUp) {
|
||||||
|
_handleKeyRepeat(-_scrollAmountOnHold);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (event.logicalKey == LogicalKeyboardKey.arrowDown) {
|
||||||
|
_handleKeyRepeat(_scrollAmountOnHold);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
onKeyDown: (event) {
|
||||||
|
if (event.logicalKey == LogicalKeyboardKey.arrowUp) {
|
||||||
|
_handleKeyDown(-_scrollAmountOnPress);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (event.logicalKey == LogicalKeyboardKey.arrowDown) {
|
||||||
|
_handleKeyDown(_scrollAmountOnPress);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (event.logicalKey == LogicalKeyboardKey.pageUp) {
|
||||||
|
_handleKeyDown(-_getViewportSize(context));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (event.logicalKey == LogicalKeyboardKey.pageDown) {
|
||||||
|
_handleKeyDown(_getViewportSize(context));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _getViewportSize(BuildContext context) {
|
||||||
|
final rb = context.findRenderObject() as RenderBox?;
|
||||||
|
if (rb != null) {
|
||||||
|
return rb.size.height.round() - 100;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,17 @@
|
|||||||
import 'package:wonders/common_libs.dart';
|
import 'package:wonders/common_libs.dart';
|
||||||
|
|
||||||
class FullScreenKeyboardListener extends StatefulWidget {
|
class FullscreenKeyboardListener extends StatefulWidget {
|
||||||
const FullScreenKeyboardListener({super.key, required this.child, this.onKeyDown, this.onKeyUp});
|
const FullscreenKeyboardListener({super.key, required this.child, this.onKeyDown, this.onKeyUp, this.onKeyRepeat});
|
||||||
final Widget child;
|
final Widget child;
|
||||||
final bool Function(KeyDownEvent event)? onKeyDown;
|
final bool Function(KeyDownEvent event)? onKeyDown;
|
||||||
final bool Function(KeyUpEvent event)? onKeyUp;
|
final bool Function(KeyUpEvent event)? onKeyUp;
|
||||||
|
final bool Function(KeyRepeatEvent event)? onKeyRepeat;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<FullScreenKeyboardListener> createState() => _FullScreenKeyboardListenerState();
|
State<FullscreenKeyboardListener> createState() => _FullscreenKeyboardListenerState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _FullScreenKeyboardListenerState extends State<FullScreenKeyboardListener> {
|
class _FullscreenKeyboardListenerState extends State<FullscreenKeyboardListener> {
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@ -31,6 +32,9 @@ class _FullScreenKeyboardListenerState extends State<FullScreenKeyboardListener>
|
|||||||
if (event is KeyUpEvent && widget.onKeyUp != null) {
|
if (event is KeyUpEvent && widget.onKeyUp != null) {
|
||||||
result = widget.onKeyUp!.call(event);
|
result = widget.onKeyUp!.call(event);
|
||||||
}
|
}
|
||||||
|
if (event is KeyRepeatEvent && widget.onKeyRepeat != null) {
|
||||||
|
result = widget.onKeyRepeat!.call(event);
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ import 'package:wonders/ui/common/centered_box.dart';
|
|||||||
import 'package:wonders/ui/common/compass_divider.dart';
|
import 'package:wonders/ui/common/compass_divider.dart';
|
||||||
import 'package:wonders/ui/common/controls/app_header.dart';
|
import 'package:wonders/ui/common/controls/app_header.dart';
|
||||||
import 'package:wonders/ui/common/curved_clippers.dart';
|
import 'package:wonders/ui/common/curved_clippers.dart';
|
||||||
|
import 'package:wonders/ui/common/fullscreen_keyboard_list_scroller.dart';
|
||||||
import 'package:wonders/ui/common/google_maps_marker.dart';
|
import 'package:wonders/ui/common/google_maps_marker.dart';
|
||||||
import 'package:wonders/ui/common/gradient_container.dart';
|
import 'package:wonders/ui/common/gradient_container.dart';
|
||||||
import 'package:wonders/ui/common/hidden_collectible.dart';
|
import 'package:wonders/ui/common/hidden_collectible.dart';
|
||||||
@ -111,8 +112,9 @@ class _WonderEditorialScreenState extends State<WonderEditorialScreen> {
|
|||||||
padding: widget.contentPadding,
|
padding: widget.contentPadding,
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
child: FocusTraversalGroup(
|
child: FocusTraversalGroup(
|
||||||
|
child: FullscreenKeyboardListScroller(
|
||||||
|
scrollController: _scroller,
|
||||||
child: CustomScrollView(
|
child: CustomScrollView(
|
||||||
primary: false,
|
|
||||||
controller: _scroller,
|
controller: _scroller,
|
||||||
scrollBehavior: ScrollConfiguration.of(context).copyWith(),
|
scrollBehavior: ScrollConfiguration.of(context).copyWith(),
|
||||||
key: PageStorageKey('editorial'),
|
key: PageStorageKey('editorial'),
|
||||||
@ -164,6 +166,7 @@ class _WonderEditorialScreenState extends State<WonderEditorialScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
|
||||||
/// Home Btn
|
/// Home Btn
|
||||||
if (showBackBtn) ...[
|
if (showBackBtn) ...[
|
||||||
|
Loading…
x
Reference in New Issue
Block a user