improved fullscreen with notch, top overlay buttons

This commit is contained in:
Thibault Deckers 2019-08-01 23:54:27 +09:00
parent a25f81f359
commit 09dedaa604
4 changed files with 113 additions and 54 deletions

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="AppTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowTranslucentNavigation">@bool/translucentNavBar</item> <!-- API19+, tinted background & request the SYSTEM_UI_FLAG_LAYOUT_STABLE and SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN flags -->
<item name="android:windowLayoutInDisplayCutoutMode">shortEdges</item> <!-- API28+, draws next to the notch in fullscreen -->
</style>
</resources>

View file

@ -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,
),
);
}
}

View file

@ -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<FullscreenPage> 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),
),

View file

@ -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<ImageEntry> 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<FullscreenBottomOverlay> {
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<Map> 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<Map> 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<FullscreenBottomOverlay> {
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,
),
),
);
}
}