From 09dedaa60455e3f2043ccda37e72d3e5b7741d5a Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Thu, 1 Aug 2019 23:54:27 +0900 Subject: [PATCH] improved fullscreen with notch, top overlay buttons --- .../app/src/main/res/values-v28/styles.xml | 7 ++ lib/widgets/common/blurred.dart | 35 ++++++ lib/widgets/fullscreen/image_page.dart | 7 +- lib/widgets/fullscreen/overlay.dart | 118 ++++++++++-------- 4 files changed, 113 insertions(+), 54 deletions(-) create mode 100644 android/app/src/main/res/values-v28/styles.xml create mode 100644 lib/widgets/common/blurred.dart diff --git a/android/app/src/main/res/values-v28/styles.xml b/android/app/src/main/res/values-v28/styles.xml new file mode 100644 index 000000000..b398f5351 --- /dev/null +++ b/android/app/src/main/res/values-v28/styles.xml @@ -0,0 +1,7 @@ + + + + diff --git a/lib/widgets/common/blurred.dart b/lib/widgets/common/blurred.dart new file mode 100644 index 000000000..1060c005c --- /dev/null +++ b/lib/widgets/common/blurred.dart @@ -0,0 +1,35 @@ +import 'dart:ui'; + +import 'package:flutter/material.dart'; + +class BlurredRect extends StatelessWidget { + final Widget child; + + const BlurredRect({Key key, this.child}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ClipRect( + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 4, sigmaY: 4), + child: child, + ), + ); + } +} + +class BlurredOval extends StatelessWidget { + final Widget child; + + const BlurredOval({Key key, this.child}) : super(key: key); + + @override + Widget build(BuildContext context) { + return ClipOval( + child: BackdropFilter( + filter: ImageFilter.blur(sigmaX: 4, sigmaY: 4), + child: child, + ), + ); + } +} diff --git a/lib/widgets/fullscreen/image_page.dart b/lib/widgets/fullscreen/image_page.dart index 7837c81e1..ecf9e7252 100644 --- a/lib/widgets/fullscreen/image_page.dart +++ b/lib/widgets/fullscreen/image_page.dart @@ -5,6 +5,7 @@ import 'package:aves/model/image_entry.dart'; import 'package:aves/widgets/fullscreen/info_page.dart'; import 'package:aves/widgets/fullscreen/overlay.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:photo_view/photo_view.dart'; import 'package:photo_view/photo_view_gallery.dart'; @@ -69,7 +70,11 @@ class FullscreenPageState extends State with SingleTickerProvide ImagePage( entries: entries, pageController: _horizontalPager, - onTap: () => _overlayVisible.value = !_overlayVisible.value, + onTap: () { + final visible = !_overlayVisible.value; + _overlayVisible.value = visible; + SystemChrome.setEnabledSystemUIOverlays(visible ? []: SystemUiOverlay.values); + }, onPageChanged: (page) => setState(() => _currentHorizontalPage = page), onScaleChanged: (state) => setState(() => _isInitialScale = state == PhotoViewScaleState.initial), ), diff --git a/lib/widgets/fullscreen/overlay.dart b/lib/widgets/fullscreen/overlay.dart index 5ca7ff18b..e8917583d 100644 --- a/lib/widgets/fullscreen/overlay.dart +++ b/lib/widgets/fullscreen/overlay.dart @@ -4,27 +4,12 @@ import 'dart:ui'; import 'package:aves/model/android_app_service.dart'; import 'package:aves/model/image_entry.dart'; import 'package:aves/model/metadata_service.dart'; +import 'package:aves/widgets/common/blurred.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; const kOverlayBackground = Colors.black26; -class Blurred extends StatelessWidget { - final Widget child; - - const Blurred({Key key, this.child}) : super(key: key); - - @override - Widget build(BuildContext context) { - return ClipRect( - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 4, sigmaY: 4), - child: child, - ), - ); - } -} - class FullscreenTopOverlay extends StatelessWidget { final List entries; final int index; @@ -35,23 +20,23 @@ class FullscreenTopOverlay extends StatelessWidget { @override Widget build(BuildContext context) { - return Blurred( - child: SafeArea( - child: Container( - height: kToolbarHeight, - child: AppBar( - title: Text('${index + 1}/${entries.length}'), - actions: [ -// IconButton(icon: Icon(Icons.delete), onPressed: delete), - IconButton( + return SafeArea( + child: Padding( + padding: EdgeInsets.all(8.0), + child: Row( + children: [ + OverlayButton( + child: BackButton(), + ), + Spacer(), + OverlayButton( + child: IconButton( icon: Icon(Icons.share), onPressed: share, tooltip: 'Share', ), - ], - elevation: 0, - backgroundColor: kOverlayBackground, - ), + ), + ], ), ), ); @@ -102,28 +87,31 @@ class _FullscreenBottomOverlayState extends State { final innerPadding = EdgeInsets.all(8.0); final mediaQuery = MediaQuery.of(context); final overlayContentMaxWidth = mediaQuery.size.width - mediaQuery.viewPadding.horizontal - innerPadding.horizontal; - return Blurred( - child: IgnorePointer( - child: Padding( - padding: mediaQuery.viewInsets + mediaQuery.viewPadding.copyWith(top: 0), - child: Container( - padding: innerPadding, - color: kOverlayBackground, - child: FutureBuilder( - future: _detailLoader, - builder: (futureContext, AsyncSnapshot snapshot) { - if (snapshot.connectionState == ConnectionState.done && !snapshot.hasError) { - _lastDetails = snapshot.data; - _lastEntry = entry; - } - return _lastEntry == null - ? SizedBox.shrink() - : _FullscreenBottomOverlayContent( - entry: _lastEntry, - details: _lastDetails, - maxWidth: overlayContentMaxWidth, - ); - }, + return BlurredRect( + child: Container( + color: kOverlayBackground, + child: IgnorePointer( + child: Padding( + padding: mediaQuery.viewInsets + mediaQuery.viewPadding.copyWith(top: 0), + child: Container( + padding: innerPadding, + child: FutureBuilder( + future: _detailLoader, + builder: (futureContext, AsyncSnapshot snapshot) { + if (snapshot.connectionState == ConnectionState.done && !snapshot.hasError) { + _lastDetails = snapshot.data; + _lastEntry = entry; + } + return _lastEntry == null + ? SizedBox.shrink() + : _FullscreenBottomOverlayContent( + entry: _lastEntry, + details: _lastDetails, + position: '${widget.index + 1}/${widget.entries.length}', + maxWidth: overlayContentMaxWidth, + ); + }, + ), ), ), ), @@ -135,9 +123,10 @@ class _FullscreenBottomOverlayState extends State { class _FullscreenBottomOverlayContent extends StatelessWidget { final ImageEntry entry; final Map details; + final String position; final double maxWidth; - _FullscreenBottomOverlayContent({this.entry, this.details, this.maxWidth}); + _FullscreenBottomOverlayContent({this.entry, this.details, this.position, this.maxWidth}); @override Widget build(BuildContext context) { @@ -159,7 +148,7 @@ class _FullscreenBottomOverlayContent extends StatelessWidget { SizedBox( width: maxWidth, child: Text( - entry.title, + '$position – ${entry.title}', overflow: TextOverflow.ellipsis, ), ), @@ -196,3 +185,26 @@ class _FullscreenBottomOverlayContent extends StatelessWidget { ); } } + +class OverlayButton extends StatelessWidget { + final Widget child; + + const OverlayButton({this.child}); + + @override + Widget build(BuildContext context) { + return BlurredOval( + child: Material( + type: MaterialType.circle, + color: kOverlayBackground, + child: Ink( + decoration: BoxDecoration( + border: Border.all(color: Colors.white30, width: 0.5), + shape: BoxShape.circle, + ), + child: child, + ), + ), + ); + } +}