fix: stabilize grid column count when alpha bar shows

This commit is contained in:
edde746
2026-04-24 19:19:39 +02:00
parent 3d023962e1
commit 49a86e402c
2 changed files with 26 additions and 11 deletions
@@ -1248,7 +1248,7 @@ class _LibraryBrowseTabState extends BaseLibraryTabState<PlexMetadata, LibraryBr
static const double _gridTopPaddingPhone = _chipsBarHeight; static const double _gridTopPaddingPhone = _chipsBarHeight;
/// Width of the alpha jump bar widget /// Width of the alpha jump bar widget
static const double _alphaJumpBarWidth = 28.0; static const double _alphaJumpBarWidth = 20.0;
/// Builds either a sliver list or sliver grid based on the view mode /// Builds either a sliver list or sliver grid based on the view mode
Widget _buildItemsSliver(BuildContext context, SettingsProvider settingsProvider) { Widget _buildItemsSliver(BuildContext context, SettingsProvider settingsProvider) {
@@ -1277,12 +1277,18 @@ class _LibraryBrowseTabState extends BaseLibraryTabState<PlexMetadata, LibraryBr
// Use 16:9 aspect ratio when browsing episodes with episode thumbnail mode // Use 16:9 aspect ratio when browsing episodes with episode thumbnail mode
final useWideRatio = final useWideRatio =
_selectedGrouping == 'episodes' && settingsProvider.episodePosterMode == EpisodePosterMode.episodeThumbnail; _selectedGrouping == 'episodes' && settingsProvider.episodePosterMode == EpisodePosterMode.episodeThumbnail;
final maxExtent = GridSizeCalculator.getMaxCrossAxisExtent(context, settingsProvider.libraryDensity); final baseMaxExtent = GridSizeCalculator.getMaxCrossAxisExtent(context, settingsProvider.libraryDensity);
final effectiveMaxExtent = useWideRatio ? baseMaxExtent * 1.8 : baseMaxExtent;
final hasAlphaBarReservation = rightPadding > 8.0;
return SliverPadding( return SliverPadding(
padding: EdgeInsets.fromLTRB(8, topPadding, rightPadding, 8), padding: EdgeInsets.fromLTRB(8, topPadding, rightPadding, 8),
sliver: SliverLayoutBuilder( sliver: SliverLayoutBuilder(
builder: (context, constraints) { builder: (context, constraints) {
final columnCount = GridSizeCalculator.getColumnCount(constraints.crossAxisExtent, maxExtent); // Compute column count from the width the grid would have without the alpha
// bar's reservation, so toggling the bar doesn't repack the grid into one
// fewer column and blow up poster size.
final baselineWidth = constraints.crossAxisExtent + (rightPadding - 8.0);
final columnCount = GridSizeCalculator.getColumnCount(baselineWidth, effectiveMaxExtent);
// Cache grid metrics for alpha jump bar scroll calculations // Cache grid metrics for alpha jump bar scroll calculations
_lastCrossAxisExtent = constraints.crossAxisExtent; _lastCrossAxisExtent = constraints.crossAxisExtent;
_currentColumnCount = columnCount; _currentColumnCount = columnCount;
@@ -1291,6 +1297,7 @@ class _LibraryBrowseTabState extends BaseLibraryTabState<PlexMetadata, LibraryBr
context: context, context: context,
density: settingsProvider.libraryDensity, density: settingsProvider.libraryDensity,
useWideAspectRatio: useWideRatio, useWideAspectRatio: useWideRatio,
maxCrossAxisExtentOverride: hasAlphaBarReservation ? constraints.crossAxisExtent / columnCount : null,
), ),
itemCount: itemCount, itemCount: itemCount,
itemBuilder: (context, index) => _buildMediaCardItem( itemBuilder: (context, index) => _buildMediaCardItem(
+16 -8
View File
@@ -10,25 +10,33 @@ class MediaGridDelegate {
/// Uses [GridSizeCalculator.getMaxCrossAxisExtent] by default. /// Uses [GridSizeCalculator.getMaxCrossAxisExtent] by default.
/// Set [usePaddingAware] to true to use [GridSizeCalculator.getMaxCrossAxisExtentWithPadding] instead. /// Set [usePaddingAware] to true to use [GridSizeCalculator.getMaxCrossAxisExtentWithPadding] instead.
/// Set [useWideAspectRatio] to true to use 16:9 aspect ratio for episode thumbnails. /// Set [useWideAspectRatio] to true to use 16:9 aspect ratio for episode thumbnails.
/// Pass [maxCrossAxisExtentOverride] to bypass the calculator and the wide-aspect multiplier —
/// the caller is then responsible for providing a fully-resolved per-cell width.
static SliverGridDelegateWithMaxCrossAxisExtent createDelegate({ static SliverGridDelegateWithMaxCrossAxisExtent createDelegate({
required BuildContext context, required BuildContext context,
required int density, required int density,
bool usePaddingAware = false, bool usePaddingAware = false,
double horizontalPadding = 16, double horizontalPadding = 16,
bool useWideAspectRatio = false, bool useWideAspectRatio = false,
double? maxCrossAxisExtentOverride,
}) { }) {
var maxCrossAxisExtent = usePaddingAware
? GridSizeCalculator.getMaxCrossAxisExtentWithPadding(context, density, horizontalPadding)
: GridSizeCalculator.getMaxCrossAxisExtent(context, density);
final aspectRatio = useWideAspectRatio final aspectRatio = useWideAspectRatio
? GridLayoutConstants.episodeGridCellAspectRatio ? GridLayoutConstants.episodeGridCellAspectRatio
: GridLayoutConstants.posterAspectRatio; : GridLayoutConstants.posterAspectRatio;
// For wide aspect ratio (16:9), increase max extent so items are larger double maxCrossAxisExtent;
// and there are fewer per row (roughly 1.8x wider to maintain similar visual area) if (maxCrossAxisExtentOverride != null) {
if (useWideAspectRatio) { maxCrossAxisExtent = maxCrossAxisExtentOverride;
maxCrossAxisExtent *= 1.8; } else {
maxCrossAxisExtent = usePaddingAware
? GridSizeCalculator.getMaxCrossAxisExtentWithPadding(context, density, horizontalPadding)
: GridSizeCalculator.getMaxCrossAxisExtent(context, density);
// For wide aspect ratio (16:9), increase max extent so items are larger
// and there are fewer per row (roughly 1.8x wider to maintain similar visual area)
if (useWideAspectRatio) {
maxCrossAxisExtent *= 1.8;
}
} }
return SliverGridDelegateWithMaxCrossAxisExtent( return SliverGridDelegateWithMaxCrossAxisExtent(