viewer: collapse motion photo pages in button row
This commit is contained in:
parent
db5b971a81
commit
e92cee781c
4 changed files with 54 additions and 17 deletions
|
@ -15,7 +15,7 @@ class ThumbnailScroller extends StatefulWidget {
|
|||
final ValueNotifier<int?> indexNotifier;
|
||||
final void Function(int index)? onTap;
|
||||
final Object? Function(AvesEntry entry)? heroTagger;
|
||||
final bool highlightable, showLocation;
|
||||
final bool scrollable, highlightable, showLocation;
|
||||
|
||||
const ThumbnailScroller({
|
||||
Key? key,
|
||||
|
@ -27,6 +27,7 @@ class ThumbnailScroller extends StatefulWidget {
|
|||
this.heroTagger,
|
||||
this.highlightable = false,
|
||||
this.showLocation = true,
|
||||
this.scrollable = true,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
|
@ -46,6 +47,10 @@ class _ThumbnailScrollerState extends State<ThumbnailScroller> {
|
|||
|
||||
ValueNotifier<int?> get indexNotifier => widget.indexNotifier;
|
||||
|
||||
bool get scrollable => widget.scrollable;
|
||||
|
||||
static double widthFor(int pageCount) => pageCount == 0 ? 0 : pageCount * thumbnailExtent + (pageCount - 1) * separatorWidth;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
@ -84,13 +89,14 @@ class _ThumbnailScrollerState extends State<ThumbnailScroller> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final marginWidth = max(0.0, (widget.availableWidth - thumbnailExtent) / 2 - separatorWidth);
|
||||
final padding = EdgeInsets.only(left: marginWidth + separatorWidth, right: marginWidth);
|
||||
final padding = scrollable ? EdgeInsets.only(left: marginWidth + separatorWidth, right: marginWidth) : EdgeInsets.zero;
|
||||
|
||||
return GridTheme(
|
||||
extent: thumbnailExtent,
|
||||
showLocation: widget.showLocation && settings.showThumbnailLocation,
|
||||
showTrash: false,
|
||||
child: SizedBox(
|
||||
width: scrollable ? null : widthFor(entryCount),
|
||||
height: thumbnailExtent,
|
||||
child: ListView.builder(
|
||||
scrollDirection: Axis.horizontal,
|
||||
|
@ -98,10 +104,12 @@ class _ThumbnailScrollerState extends State<ThumbnailScroller> {
|
|||
// as of Flutter v2.10.2, `FixedExtentScrollController` can only be used with `ListWheelScrollView`
|
||||
// and `FixedExtentScrollPhysics` can only be used with Scrollables that uses the `FixedExtentScrollController`
|
||||
// so we use `KnownExtentScrollPhysics`, adapted from `FixedExtentScrollPhysics` without the constraints
|
||||
physics: KnownExtentScrollPhysics(
|
||||
physics: scrollable
|
||||
? KnownExtentScrollPhysics(
|
||||
indexToScrollOffset: indexToScrollOffset,
|
||||
scrollOffsetToIndex: scrollOffsetToIndex,
|
||||
),
|
||||
)
|
||||
: const NeverScrollableScrollPhysics(),
|
||||
padding: padding,
|
||||
itemExtent: itemExtent,
|
||||
itemBuilder: (context, index) => _buildThumbnail(index),
|
||||
|
@ -152,6 +160,8 @@ class _ThumbnailScrollerState extends State<ThumbnailScroller> {
|
|||
}
|
||||
|
||||
Future<void> _goTo(int index) async {
|
||||
if (!scrollable) return;
|
||||
|
||||
final targetOffset = indexToScrollOffset(index);
|
||||
final offsetDelta = (targetOffset - _scrollController.offset).abs();
|
||||
|
||||
|
|
|
@ -136,13 +136,23 @@ class _BottomOverlayContentState extends State<_BottomOverlayContent> {
|
|||
return Selector<MediaQueryData, double>(
|
||||
selector: (context, mq) => mq.size.width,
|
||||
builder: (context, mqWidth, child) {
|
||||
final viewerButtonRow = ViewerButtonRow(
|
||||
mainEntry: mainEntry,
|
||||
pageEntry: pageEntry,
|
||||
scale: _buttonScale,
|
||||
canToggleFavourite: widget.hasCollection,
|
||||
);
|
||||
|
||||
final showMultiPageOverlay = mainEntry.isMultiPage && multiPageController != null;
|
||||
final collapsedPageScroller = mainEntry.isMotionPhoto;
|
||||
|
||||
return SizedBox(
|
||||
width: mqWidth,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (mainEntry.isMultiPage && multiPageController != null)
|
||||
if (showMultiPageOverlay && !collapsedPageScroller)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8),
|
||||
child: FadeTransition(
|
||||
|
@ -150,15 +160,30 @@ class _BottomOverlayContentState extends State<_BottomOverlayContent> {
|
|||
child: MultiPageOverlay(
|
||||
controller: multiPageController,
|
||||
availableWidth: mqWidth,
|
||||
scrollable: true,
|
||||
),
|
||||
),
|
||||
),
|
||||
ViewerButtonRow(
|
||||
mainEntry: mainEntry,
|
||||
pageEntry: pageEntry,
|
||||
scale: _buttonScale,
|
||||
canToggleFavourite: widget.hasCollection,
|
||||
(showMultiPageOverlay && collapsedPageScroller)
|
||||
? Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8),
|
||||
child: MultiPageOverlay(
|
||||
controller: multiPageController,
|
||||
availableWidth: mqWidth,
|
||||
scrollable: false,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(child: viewerButtonRow),
|
||||
],
|
||||
)
|
||||
: viewerButtonRow,
|
||||
if (settings.showOverlayThumbnailPreview)
|
||||
FadeTransition(
|
||||
opacity: _thumbnailOpacity,
|
||||
|
|
|
@ -8,11 +8,13 @@ import 'package:provider/provider.dart';
|
|||
class MultiPageOverlay extends StatefulWidget {
|
||||
final MultiPageController controller;
|
||||
final double availableWidth;
|
||||
final bool scrollable;
|
||||
|
||||
const MultiPageOverlay({
|
||||
Key? key,
|
||||
required this.controller,
|
||||
required this.availableWidth,
|
||||
required this.scrollable,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
|
@ -66,6 +68,7 @@ class _MultiPageOverlayState extends State<MultiPageOverlay> {
|
|||
entryCount: multiPageInfo?.pageCount ?? 0,
|
||||
entryBuilder: (page) => multiPageInfo?.getPageEntryByIndex(page),
|
||||
indexNotifier: controller.pageNotifier,
|
||||
scrollable: widget.scrollable,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -105,11 +105,10 @@ class ViewerButtonRow extends StatelessWidget {
|
|||
return SafeArea(
|
||||
top: false,
|
||||
bottom: false,
|
||||
child: Selector<MediaQueryData, double>(
|
||||
selector: (context, mq) => mq.size.width - mq.padding.horizontal,
|
||||
builder: (context, mqWidth, child) {
|
||||
child: LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final buttonWidth = OverlayButton.getSize(context);
|
||||
final availableCount = ((mqWidth - outerPadding * 2) / (buttonWidth + innerPadding)).floor();
|
||||
final availableCount = ((constraints.maxWidth - outerPadding * 2) / (buttonWidth + innerPadding)).floor();
|
||||
return Selector<Settings, bool>(
|
||||
selector: (context, s) => s.isRotationLocked,
|
||||
builder: (context, s, child) {
|
||||
|
|
Loading…
Reference in a new issue