fix(flutter): keep artist avatars round in the Library grid
ArtistCard hardcoded its avatar at Container(width: 124, height: 124) inside a ClipOval. In the Library Artists 3-column grid the cell is narrower than the card's nominal 140dp width — on a typical phone the cell is ~109dp, the padded inner content area ~93dp. The parent constrained the Container's width to ~93dp but the explicit height stayed 124dp, so ClipOval clipped a 93×124 rectangle and the avatar rendered as a vertical ellipse. Fix mirrors AlbumCard's pattern: ArtistCard takes an optional `width` parameter (default 140 for horizontal carousels) and derives coverSize = width - 16, so the Container is always square. ArtistsTab now uses LayoutBuilder to compute cell width and passes it through, same as AlbumsTab. Avatar stays a true circle at any cell width. mainAxisExtent on the grid replaces the previous fixed childAspectRatio so cell height tracks cellW + name line, with slack matching AlbumsTab's overflow guard.
This commit is contained in:
@@ -398,36 +398,52 @@ class _ArtistsTab extends ConsumerWidget {
|
||||
// Listen for scroll-near-bottom and ask the notifier
|
||||
// to fetch the next page. 800px lookahead so the next
|
||||
// page lands before the user reaches the visible end.
|
||||
child: NotificationListener<ScrollNotification>(
|
||||
onNotification: (n) {
|
||||
if (n.metrics.pixels >=
|
||||
n.metrics.maxScrollExtent - 800) {
|
||||
ref
|
||||
.read(_libraryArtistsProvider.notifier)
|
||||
.loadMore();
|
||||
}
|
||||
return false;
|
||||
},
|
||||
child: GridView.builder(
|
||||
padding: const EdgeInsets.all(8),
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 3,
|
||||
mainAxisSpacing: 8,
|
||||
crossAxisSpacing: 8,
|
||||
childAspectRatio: 0.78,
|
||||
),
|
||||
itemCount: page.items.length,
|
||||
itemBuilder: (ctx, i) {
|
||||
final artist = page.items[i];
|
||||
return ArtistCard(
|
||||
artist: artist,
|
||||
onTap: () => ctx.push('/artists/${artist.id}',
|
||||
extra: artist),
|
||||
);
|
||||
// LayoutBuilder + cell-aware ArtistCard width mirrors
|
||||
// the AlbumsTab pattern so the circular avatar stays
|
||||
// a true circle on narrow grid cells.
|
||||
child: LayoutBuilder(builder: (ctx, constraints) {
|
||||
const cols = 3;
|
||||
const sidePad = 8.0;
|
||||
const gap = 8.0;
|
||||
final cellW = (constraints.maxWidth -
|
||||
sidePad * 2 -
|
||||
gap * (cols - 1)) /
|
||||
cols;
|
||||
// avatar (cellW - 16) + gap (8) + 1 line name (~18)
|
||||
// + slack matched to AlbumsTab's overflow guard.
|
||||
final cellH = (cellW - 16) + 8 + 18 + 8;
|
||||
return NotificationListener<ScrollNotification>(
|
||||
onNotification: (n) {
|
||||
if (n.metrics.pixels >=
|
||||
n.metrics.maxScrollExtent - 800) {
|
||||
ref
|
||||
.read(_libraryArtistsProvider.notifier)
|
||||
.loadMore();
|
||||
}
|
||||
return false;
|
||||
},
|
||||
),
|
||||
),
|
||||
child: GridView.builder(
|
||||
padding: const EdgeInsets.all(sidePad),
|
||||
gridDelegate:
|
||||
SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: cols,
|
||||
mainAxisExtent: cellH,
|
||||
mainAxisSpacing: gap,
|
||||
crossAxisSpacing: gap,
|
||||
),
|
||||
itemCount: page.items.length,
|
||||
itemBuilder: (ctx, i) {
|
||||
final artist = page.items[i];
|
||||
return ArtistCard(
|
||||
artist: artist,
|
||||
width: cellW,
|
||||
onTap: () => ctx.push('/artists/${artist.id}',
|
||||
extra: artist),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user