split FullscreenBody

This commit is contained in:
Thibault Deckers 2019-12-24 11:45:03 +09:00
parent bfe2b4d319
commit 1b6759384e

View file

@ -58,7 +58,6 @@ class FullscreenBody extends StatefulWidget {
} }
class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProviderStateMixin { class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProviderStateMixin {
bool _isInitialScale = true;
int _currentHorizontalPage, _currentVerticalPage = imagePage; int _currentHorizontalPage, _currentVerticalPage = imagePage;
PageController _horizontalPager, _verticalPager; PageController _horizontalPager, _verticalPager;
final ValueNotifier<bool> _overlayVisible = ValueNotifier(true); final ValueNotifier<bool> _overlayVisible = ValueNotifier(true);
@ -122,6 +121,8 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final entry = _currentHorizontalPage != null && _currentHorizontalPage < entries.length ? entries[_currentHorizontalPage] : null; final entry = _currentHorizontalPage != null && _currentHorizontalPage < entries.length ? entries[_currentHorizontalPage] : null;
final showOverlay = entry != null && _currentVerticalPage == imagePage;
final videoController = showOverlay && entry.isVideo ? _videoControllers.firstWhere((kv) => kv.item1 == entry.path, orElse: () => null)?.item2 : null;
return WillPopScope( return WillPopScope(
onWillPop: () { onWillPop: () {
if (_currentVerticalPage == infoPage) { if (_currentVerticalPage == infoPage) {
@ -133,78 +134,54 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
}, },
child: Stack( child: Stack(
children: [ children: [
PageView( FullscreenVerticalPageView(
scrollDirection: Axis.vertical, collection: collection,
controller: _verticalPager, entry: entry,
physics: _isInitialScale ? const PageScrollPhysics() : const NeverScrollableScrollPhysics(), videoControllers: _videoControllers,
onPageChanged: _onVerticalPageChanged, verticalPager: _verticalPager,
children: [ horizontalPager: _horizontalPager,
const SizedBox(), onVerticalPageChanged: _onVerticalPageChanged,
Container( onHorizontalPageChanged: _onHorizontalPageChanged,
color: Colors.black, onImageTap: () => _overlayVisible.value = !_overlayVisible.value,
child: ImagePage( onImagePageRequested: () => _goToVerticalPage(imagePage),
collection: collection, ),
pageController: _horizontalPager, if (showOverlay) FullscreenTopOverlay(
onTap: () => _overlayVisible.value = !_overlayVisible.value, entries: entries,
onPageChanged: _onHorizontalPageChanged, index: _currentHorizontalPage,
onScaleChanged: (state) => setState(() => _isInitialScale = state == PhotoViewScaleState.initial), scale: _topOverlayScale,
videoControllers: _videoControllers, viewInsets: _frozenViewInsets,
), viewPadding: _frozenViewPadding,
), onActionSelected: (action) => _actionDelegate.onActionSelected(context, entry, action),
NotificationListener( ),
onNotification: (notification) { if (showOverlay) Positioned(
if (notification is BackUpNotification) _goToVerticalPage(imagePage); bottom: 0,
return false; child: Column(
}, children: [
child: InfoPage(collection: collection, entry: entry), if (videoController != null)
), VideoControlOverlay(
], entry: entry,
controller: videoController,
scale: _topOverlayScale,
viewInsets: _frozenViewInsets,
viewPadding: _frozenViewPadding,
),
SlideTransition(
position: _bottomOverlayOffset,
child: FullscreenBottomOverlay(
entries: entries,
index: _currentHorizontalPage,
viewInsets: _frozenViewInsets,
viewPadding: _frozenViewPadding,
),
),
],
),
), ),
..._buildOverlay(entry)
], ],
), ),
); );
} }
List<Widget> _buildOverlay(ImageEntry entry) {
if (entry == null || _currentVerticalPage != imagePage) return [];
final videoController = entry.isVideo ? _videoControllers.firstWhere((kv) => kv.item1 == entry.path, orElse: () => null)?.item2 : null;
return [
FullscreenTopOverlay(
entries: entries,
index: _currentHorizontalPage,
scale: _topOverlayScale,
viewInsets: _frozenViewInsets,
viewPadding: _frozenViewPadding,
onActionSelected: (action) => _actionDelegate.onActionSelected(context, entry, action),
),
Positioned(
bottom: 0,
child: Column(
children: [
if (videoController != null)
VideoControlOverlay(
entry: entry,
controller: videoController,
scale: _topOverlayScale,
viewInsets: _frozenViewInsets,
viewPadding: _frozenViewPadding,
),
SlideTransition(
position: _bottomOverlayOffset,
child: FullscreenBottomOverlay(
entries: entries,
index: _currentHorizontalPage,
viewInsets: _frozenViewInsets,
viewPadding: _frozenViewPadding,
),
),
],
),
)
];
}
Future<void> _goToVerticalPage(int page) { Future<void> _goToVerticalPage(int page) {
return _verticalPager.animateToPage( return _verticalPager.animateToPage(
page, page,
@ -271,3 +248,62 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
} }
} }
} }
class FullscreenVerticalPageView extends StatefulWidget {
final ImageCollection collection;
final ImageEntry entry;
final List<Tuple2<String, VideoPlayerController>> videoControllers;
final PageController horizontalPager, verticalPager;
final void Function(int page) onVerticalPageChanged, onHorizontalPageChanged;
final VoidCallback onImageTap, onImagePageRequested;
const FullscreenVerticalPageView({
@required this.collection,
@required this.entry,
@required this.videoControllers,
@required this.verticalPager,
@required this.horizontalPager,
@required this.onVerticalPageChanged,
@required this.onHorizontalPageChanged,
@required this.onImageTap,
@required this.onImagePageRequested,
});
@override
_FullscreenVerticalPageViewState createState() => _FullscreenVerticalPageViewState();
}
class _FullscreenVerticalPageViewState extends State<FullscreenVerticalPageView> {
bool _isInitialScale = true;
@override
Widget build(BuildContext context) {
return PageView(
scrollDirection: Axis.vertical,
controller: widget.verticalPager,
physics: _isInitialScale ? const PageScrollPhysics() : const NeverScrollableScrollPhysics(),
onPageChanged: widget.onVerticalPageChanged,
children: [
const SizedBox(),
Container(
color: Colors.black,
child: ImagePage(
collection: widget.collection,
pageController: widget.horizontalPager,
onTap: widget.onImageTap,
onPageChanged: widget.onHorizontalPageChanged,
onScaleChanged: (state) => setState(() => _isInitialScale = state == PhotoViewScaleState.initial),
videoControllers: widget.videoControllers,
),
),
NotificationListener(
onNotification: (notification) {
if (notification is BackUpNotification) widget.onImagePageRequested();
return false;
},
child: InfoPage(collection: widget.collection, entry: widget.entry),
),
],
);
}
}