@@ -22,6 +22,7 @@ import '../../../utils/plex_image_helper.dart';
|
||||
import '../../../utils/provider_extensions.dart';
|
||||
import '../../../widgets/app_icon.dart';
|
||||
import '../../../widgets/focus_builders.dart';
|
||||
import '../../../utils/scroll_utils.dart';
|
||||
import '../../../widgets/horizontal_scroll_with_arrows.dart';
|
||||
import '../../../widgets/plex_optimized_image.dart';
|
||||
import '../live_tv_show_schedule_screen.dart';
|
||||
@@ -346,17 +347,13 @@ class _LiveTvHubSectionState extends State<_LiveTvHubSection> {
|
||||
}
|
||||
|
||||
void _scrollToIndex(int index, {bool animate = true}) {
|
||||
if (!_scrollController.hasClients || _itemExtent <= 0) return;
|
||||
|
||||
final viewport = _scrollController.position.viewportDimension;
|
||||
final targetCenter = _leadingPadding + (index * _itemExtent) + (_itemExtent / 2);
|
||||
final desiredOffset = (targetCenter - (viewport / 2)).clamp(0.0, _scrollController.position.maxScrollExtent);
|
||||
|
||||
if (animate) {
|
||||
_scrollController.animateTo(desiredOffset, duration: const Duration(milliseconds: 150), curve: Curves.easeOut);
|
||||
} else {
|
||||
_scrollController.jumpTo(desiredOffset);
|
||||
}
|
||||
scrollListToIndex(
|
||||
_scrollController,
|
||||
index,
|
||||
itemExtent: _itemExtent,
|
||||
leadingPadding: _leadingPadding,
|
||||
animate: animate,
|
||||
);
|
||||
}
|
||||
|
||||
KeyEventResult _handleKeyEvent(FocusNode _, KeyEvent event) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,25 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
/// Scroll a horizontal list to center the item at the given index.
|
||||
///
|
||||
/// Assumes items are laid out with [leadingPadding] before the first item,
|
||||
/// and each item occupies [itemExtent] pixels (including per-item padding).
|
||||
void scrollListToIndex(
|
||||
ScrollController controller,
|
||||
int index, {
|
||||
required double itemExtent,
|
||||
double leadingPadding = 12.0,
|
||||
bool animate = true,
|
||||
}) {
|
||||
if (!controller.hasClients || itemExtent <= 0) return;
|
||||
|
||||
final viewport = controller.position.viewportDimension;
|
||||
final targetCenter = leadingPadding + (index * itemExtent) + (itemExtent / 2);
|
||||
final desiredOffset = (targetCenter - (viewport / 2)).clamp(0.0, controller.position.maxScrollExtent);
|
||||
|
||||
if (animate) {
|
||||
controller.animateTo(desiredOffset, duration: const Duration(milliseconds: 150), curve: Curves.easeOut);
|
||||
} else {
|
||||
controller.jumpTo(desiredOffset);
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@ import '../screens/hub_detail_screen.dart';
|
||||
import '../utils/media_navigation_helper.dart';
|
||||
import 'focus_builders.dart';
|
||||
import 'media_card.dart';
|
||||
import '../utils/scroll_utils.dart';
|
||||
import 'horizontal_scroll_with_arrows.dart';
|
||||
import '../i18n/strings.g.dart';
|
||||
|
||||
@@ -169,17 +170,13 @@ class HubSectionState extends State<HubSection> {
|
||||
|
||||
/// Scroll to center the item at the given index
|
||||
void _scrollToIndex(int index, {bool animate = true}) {
|
||||
if (!_scrollController.hasClients || _itemExtent <= 0) return;
|
||||
|
||||
final viewport = _scrollController.position.viewportDimension;
|
||||
final targetCenter = _leadingPadding + (index * _itemExtent) + (_itemExtent / 2);
|
||||
final desiredOffset = (targetCenter - (viewport / 2)).clamp(0.0, _scrollController.position.maxScrollExtent);
|
||||
|
||||
if (animate) {
|
||||
_scrollController.animateTo(desiredOffset, duration: const Duration(milliseconds: 150), curve: Curves.easeOut);
|
||||
} else {
|
||||
_scrollController.jumpTo(desiredOffset);
|
||||
}
|
||||
scrollListToIndex(
|
||||
_scrollController,
|
||||
index,
|
||||
itemExtent: _itemExtent,
|
||||
leadingPadding: _leadingPadding,
|
||||
animate: animate,
|
||||
);
|
||||
}
|
||||
|
||||
/// Handle ALL key events at the hub level
|
||||
|
||||
Reference in New Issue
Block a user