fullscreen: swipe down to pop

This commit is contained in:
Thibault Deckers 2019-11-24 18:29:16 +09:00
parent 6203b98ff4
commit 1976e10dee
4 changed files with 53 additions and 61 deletions

View file

@ -147,14 +147,15 @@ class SectionSliver extends StatelessWidget {
);
}
Future _showFullscreen(BuildContext context, ImageEntry entry) {
return Navigator.push(
_showFullscreen(BuildContext context, ImageEntry entry) {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FullscreenPage(
collection: collection,
initialUri: entry.uri,
),
fullscreenDialog: true,
),
);
}

View file

@ -28,41 +28,9 @@ class FullscreenPage extends AnimatedWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: FullscreenBody(
return FullscreenBody(
collection: collection,
initialUri: initialUri,
),
resizeToAvoidBottomInset: false,
// Hero(
// tag: uri,
// child: Stack(
// children: [
// Center(
// child: widget.thumbnail == null
// ? CircularProgressIndicator()
// : Image.memory(
// widget.thumbnail,
// width: requestWidth,
// height: requestHeight,
// fit: BoxFit.contain,
// ),
// ),
// Center(
// child: FadeInImage(
// placeholder: MemoryImage(kTransparentImage),
// image: FileImage(File(path)),
// fadeOutDuration: Duration(milliseconds: 1),
// fadeInDuration: Duration(milliseconds: 200),
// width: requestWidth,
// height: requestHeight,
// fit: BoxFit.contain,
// ),
// ),
// ],
// ),
// ),
);
}
}
@ -83,7 +51,7 @@ class FullscreenBody extends StatefulWidget {
class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProviderStateMixin {
bool _isInitialScale = true;
int _currentHorizontalPage, _currentVerticalPage = 0;
int _currentHorizontalPage, _currentVerticalPage = imagePage;
PageController _horizontalPager, _verticalPager;
ValueNotifier<bool> _overlayVisible = ValueNotifier(true);
AnimationController _overlayAnimationController;
@ -97,6 +65,10 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
List<ImageEntry> get entries => widget.collection.sortedEntries;
static const transitionPage = 0;
static const imagePage = 1;
static const infoPage = 2;
@override
void initState() {
super.initState();
@ -119,7 +91,7 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
_overlayVisible.addListener(onOverlayVisibleChange);
_actionDelegate = FullscreenActionDelegate(
collection: collection,
showInfo: () => goToVerticalPage(1),
showInfo: () => goToVerticalPage(infoPage),
);
initVideoController();
initOverlay();
@ -144,11 +116,11 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
final entry = _currentHorizontalPage != null && _currentHorizontalPage < entries.length ? entries[_currentHorizontalPage] : null;
return WillPopScope(
onWillPop: () {
if (_currentVerticalPage == 1) {
goToVerticalPage(0);
if (_currentVerticalPage == infoPage) {
goToVerticalPage(imagePage);
return Future.value(false);
}
SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
_onLeave();
return Future.value(true);
},
child: Stack(
@ -157,9 +129,12 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
scrollDirection: Axis.vertical,
controller: _verticalPager,
physics: _isInitialScale ? PageScrollPhysics() : NeverScrollableScrollPhysics(),
onPageChanged: (page) => setState(() => _currentVerticalPage = page),
onPageChanged: _onVerticalPageChanged,
children: [
ImagePage(
SizedBox(),
Container(
color: Colors.black,
child: ImagePage(
collection: collection,
pageController: _horizontalPager,
onTap: () => _overlayVisible.value = !_overlayVisible.value,
@ -167,9 +142,10 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
onScaleChanged: (state) => setState(() => _isInitialScale = state == PhotoViewScaleState.initial),
videoControllers: _videoControllers,
),
),
NotificationListener(
onNotification: (notification) {
if (notification is BackUpNotification) goToVerticalPage(0);
if (notification is BackUpNotification) goToVerticalPage(imagePage);
return false;
},
child: InfoPage(collection: collection, entry: entry),
@ -183,7 +159,7 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
}
List<Widget> _buildOverlay(ImageEntry entry) {
if (entry == null || _currentVerticalPage != 0) return [];
if (entry == null || _currentVerticalPage != imagePage) return [];
final videoController = entry.isVideo ? _videoControllers.firstWhere((kv) => kv.item1 == entry.path, orElse: () => null)?.item2 : null;
return [
FullscreenTopOverlay(
@ -229,15 +205,29 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
);
}
_onVerticalPageChanged(page) {
setState(() => _currentVerticalPage = page);
if (_currentVerticalPage == transitionPage) {
_onLeave();
Navigator.pop(context);
}
}
_onLeave() => _showSystemUI();
_showSystemUI() => SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
_hideSystemUI() => SystemChrome.setEnabledSystemUIOverlays([]);
onOverlayVisibleChange() async {
if (_overlayVisible.value) {
SystemChrome.setEnabledSystemUIOverlays(SystemUiOverlay.values);
_showSystemUI();
_overlayAnimationController.forward();
} else {
final mediaQuery = MediaQuery.of(context);
_frozenViewInsets = mediaQuery.viewInsets;
_frozenViewPadding = mediaQuery.viewPadding;
SystemChrome.setEnabledSystemUIOverlays([]);
_hideSystemUI();
await _overlayAnimationController.reverse();
_frozenViewInsets = null;
_frozenViewPadding = null;

View file

@ -73,6 +73,7 @@ class ImagePageState extends State<ImagePage> with AutomaticKeepAliveClientMixin
loadingChild: Center(
child: CircularProgressIndicator(),
),
backgroundDecoration: BoxDecoration(color: Colors.transparent),
pageController: widget.pageController,
onPageChanged: widget.onPageChanged,
scaleStateChangedCallback: widget.onScaleChanged,

View file

@ -100,7 +100,7 @@ packages:
name: flutter_svg
url: "https://pub.dartlang.org"
source: hosted
version: "0.14.4"
version: "0.15.0"
flutter_test:
dependency: "direct dev"
description: flutter
@ -119,7 +119,7 @@ packages:
name: google_maps_flutter
url: "https://pub.dartlang.org"
source: hosted
version: "0.5.21+8"
version: "0.5.21+12"
image:
dependency: transitive
description:
@ -203,7 +203,7 @@ packages:
name: photo_view
url: "https://pub.dartlang.org"
source: hosted
version: "0.8.0"
version: "0.9.0"
printing:
dependency: "direct main"
description:
@ -231,7 +231,7 @@ packages:
name: shared_preferences
url: "https://pub.dartlang.org"
source: hosted
version: "0.5.4+3"
version: "0.5.4+5"
sky_engine:
dependency: transitive
description: flutter
@ -278,7 +278,7 @@ packages:
name: synchronized
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.0+1"
version: "2.1.0+2"
term_glyph:
dependency: transitive
description:
@ -334,7 +334,7 @@ packages:
name: video_player
url: "https://pub.dartlang.org"
source: hosted
version: "0.10.2+5"
version: "0.10.3+1"
xml:
dependency: transitive
description:
@ -344,4 +344,4 @@ packages:
version: "3.5.0"
sdks:
dart: ">=2.5.0 <3.0.0"
flutter: ">=1.9.1 <2.0.0"
flutter: ">=1.9.1+hotfix.5 <2.0.0"