Expose focusNode for HiddenCollectible to improve keyboard UX in the photo_gallery
Improve readability of _handleKeyDown method
This commit is contained in:
parent
9d2409cc9d
commit
663ad161fd
@ -6,7 +6,7 @@ import 'package:wonders/ui/common/utils/app_haptics.dart';
|
||||
import 'package:wonders/ui/screens/collectible_found/collectible_found_screen.dart';
|
||||
|
||||
class CollectibleItem extends StatelessWidget with GetItMixin {
|
||||
CollectibleItem(this.collectible, {this.size = 64.0, Key? key}) : super(key: key) {
|
||||
CollectibleItem(this.collectible, {this.size = 64.0, Key? key, this.focus}) : super(key: key) {
|
||||
// pre-fetch the image, so it's ready if we show the collectible found screen.
|
||||
_imageProvider = NetworkImage(collectible.imageUrl);
|
||||
_imageProvider.resolve(ImageConfiguration()).addListener(ImageStreamListener((_, __) {}));
|
||||
@ -15,6 +15,7 @@ class CollectibleItem extends StatelessWidget with GetItMixin {
|
||||
final CollectibleData collectible;
|
||||
final double size;
|
||||
late final ImageProvider _imageProvider;
|
||||
final FocusNode? focus;
|
||||
|
||||
void _handleTap(BuildContext context) async {
|
||||
final screen = CollectibleFoundScreen(collectible: collectible, imageProvider: _imageProvider);
|
||||
@ -39,6 +40,7 @@ class CollectibleItem extends StatelessWidget with GetItMixin {
|
||||
// Note: In order for the collapse animation to run properly, we must return a non-zero height or width.
|
||||
closedBuilder: (_) => SizedBox(width: 1, height: 0),
|
||||
openBuilder: (_) => AppBtn.basic(
|
||||
focusNode: focus,
|
||||
semanticLabel: $strings.collectibleItemSemanticCollectible,
|
||||
onPressed: () => _handleTap(context),
|
||||
enableFeedback: false,
|
||||
|
@ -5,13 +5,15 @@ import 'package:wonders/ui/common/collectible_item.dart';
|
||||
/// The item is looked up via index, and expects that 3 items always exist for each wonder.
|
||||
/// If `wonders` is empty, then the collectible is always shown.
|
||||
class HiddenCollectible extends StatelessWidget with GetItMixin {
|
||||
HiddenCollectible(this.currentWonder, {Key? key, required this.index, this.matches = const [], this.size = 64})
|
||||
HiddenCollectible(this.currentWonder,
|
||||
{Key? key, required this.index, this.matches = const [], this.size = 64, this.focus})
|
||||
: assert(index <= 2, 'index should not exceed 2'),
|
||||
super(key: key);
|
||||
final int index;
|
||||
final double size;
|
||||
final List<WonderType> matches;
|
||||
final WonderType currentWonder;
|
||||
final FocusNode? focus;
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final data = collectiblesLogic.forWonder(currentWonder);
|
||||
@ -19,6 +21,6 @@ class HiddenCollectible extends StatelessWidget with GetItMixin {
|
||||
if (matches.isNotEmpty && matches.contains(currentWonder) == false) {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
return CollectibleItem(data[index], size: size);
|
||||
return CollectibleItem(data[index], size: size, focus: focus);
|
||||
}
|
||||
}
|
||||
|
@ -99,8 +99,6 @@ class _PhotoGalleryState extends State<PhotoGallery> {
|
||||
}
|
||||
|
||||
bool _handleKeyDown(KeyDownEvent event) {
|
||||
var newIndex = -1;
|
||||
bool handled = false;
|
||||
final key = event.logicalKey;
|
||||
Map<LogicalKeyboardKey, int> keyActions = {
|
||||
LogicalKeyboardKey.arrowUp: -_gridSize,
|
||||
@ -109,24 +107,22 @@ class _PhotoGalleryState extends State<PhotoGallery> {
|
||||
LogicalKeyboardKey.arrowLeft: -1,
|
||||
};
|
||||
|
||||
int? action = keyActions[key];
|
||||
if (action != null) {
|
||||
newIndex = _index + action;
|
||||
handled = true;
|
||||
bool isRightSide = _index % _gridSize == _gridSize - 1;
|
||||
if (isRightSide && key == LogicalKeyboardKey.arrowRight) {
|
||||
newIndex = -1;
|
||||
}
|
||||
bool isLeftSide = _index % _gridSize == 0;
|
||||
if (isLeftSide && key == LogicalKeyboardKey.arrowLeft) newIndex = -1;
|
||||
if (newIndex > _gridSize * _gridSize) {
|
||||
newIndex = -1;
|
||||
}
|
||||
if (newIndex >= 0) {
|
||||
_setIndex(newIndex);
|
||||
}
|
||||
// Apply key action, exit early if no action is defined
|
||||
int? actionValue = keyActions[key];
|
||||
if (actionValue == null) return false;
|
||||
int newIndex = _index + actionValue;
|
||||
|
||||
// Block actions along edges of the grid
|
||||
bool isRightSide = _index % _gridSize == _gridSize - 1;
|
||||
bool isLeftSide = _index % _gridSize == 0;
|
||||
bool outOfBounds = newIndex < 0 || newIndex >= _imgCount;
|
||||
if ((isRightSide && key == LogicalKeyboardKey.arrowRight) ||
|
||||
(isLeftSide && key == LogicalKeyboardKey.arrowLeft) ||
|
||||
outOfBounds) {
|
||||
return false;
|
||||
}
|
||||
return handled;
|
||||
_setIndex(newIndex);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Converts a swipe direction into a new index
|
||||
@ -274,14 +270,16 @@ class _PhotoGalleryState extends State<PhotoGallery> {
|
||||
liveRegion: isSelected,
|
||||
onIncrease: () => _handleImageTapped(_index + 1, false),
|
||||
onDecrease: () => _handleImageTapped(_index - 1, false),
|
||||
child: AppBtn.basic(
|
||||
semanticLabel: semanticLbl,
|
||||
focusNode: _focusNodes[index],
|
||||
onFocusChanged: (isFocused) => _handleImageFocusChanged(index, isFocused),
|
||||
onPressed: () => _handleImageTapped(index, isSelected),
|
||||
child: _checkCollectibleIndex(index)
|
||||
? Center(child: HiddenCollectible(widget.wonderType, index: 1, size: 100))
|
||||
: ClipRRect(
|
||||
child: _checkCollectibleIndex(index)
|
||||
? Center(
|
||||
child: HiddenCollectible(widget.wonderType, index: 1, size: 100, focus: _focusNodes[index]),
|
||||
)
|
||||
: AppBtn.basic(
|
||||
semanticLabel: semanticLbl,
|
||||
focusNode: _focusNodes[index],
|
||||
onFocusChanged: (isFocused) => _handleImageFocusChanged(index, isFocused),
|
||||
onPressed: () => _handleImageTapped(index, isSelected),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: SizedBox(
|
||||
width: imgSize.width,
|
||||
@ -303,7 +301,7 @@ class _PhotoGalleryState extends State<PhotoGallery> {
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
|
Loading…
x
Reference in New Issue
Block a user