mirror of
https://github.com/friebetill/TubeCards.git
synced 2025-08-14 09:54:12 +08:00
58 lines
1.8 KiB
Dart
58 lines
1.8 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
/// A horizontal scrollable widget with a snap effect.
|
|
///
|
|
/// When the user is done scrolling, it automatically snaps to the next item.
|
|
class SnapList extends StatelessWidget {
|
|
const SnapList({
|
|
required this.itemWidth,
|
|
required this.paddingWidth,
|
|
required this.itemCount,
|
|
required this.itemBuilder,
|
|
Key? key,
|
|
}) : super(key: key);
|
|
|
|
/// The width of an item.
|
|
///
|
|
/// The width should not be greater than 360 pixels - [paddingWidth],
|
|
/// otherwise the next item will not be displayed on 360 pixel screens.
|
|
///
|
|
/// Since there is no cache extent yet, there is no way to preload the next
|
|
/// items otherwise, see https://bit.ly/34j83mu.
|
|
final double itemWidth;
|
|
|
|
final double paddingWidth;
|
|
|
|
final int itemCount;
|
|
|
|
final Widget Function(BuildContext, int) itemBuilder;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return PageView.builder(
|
|
controller: PageController(
|
|
viewportFraction:
|
|
(itemWidth + paddingWidth) / MediaQuery.of(context).size.width,
|
|
),
|
|
// Make sure items are not clipped when there is horizontal space
|
|
// left next to the last item and the user scrolls.
|
|
clipBehavior: Clip.none,
|
|
padEnds: false,
|
|
itemCount: itemCount,
|
|
itemBuilder: (context, i) {
|
|
return Padding(
|
|
padding: EdgeInsets.only(
|
|
// This will make the rightmost item wider by paddingWidth pixels
|
|
// than the other widgets. The alternative is to make this item the
|
|
// same size as the others, but then the padding is too large for
|
|
// the rightmost widget. The slightly bigger widget is probably
|
|
// less noticeable.
|
|
right: i != itemCount - 1 ? paddingWidth : 0,
|
|
),
|
|
child: itemBuilder(context, i),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|