mirror of
https://github.com/vodemn/m3_lightmeter.git
synced 2024-11-22 07:20:39 +00:00
2-column layout
2-column layout removed settings screen route animation
This commit is contained in:
parent
10764086ad
commit
9abad012e3
6 changed files with 91 additions and 356 deletions
|
@ -3,13 +3,11 @@ import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:lightmeter/data/permissions_service.dart';
|
import 'package:lightmeter/data/permissions_service.dart';
|
||||||
import 'package:lightmeter/screens/settings/settings_page_route_builder.dart';
|
|
||||||
import 'package:lightmeter/screens/settings/settings_screen.dart';
|
import 'package:lightmeter/screens/settings/settings_screen.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
import 'generated/l10n.dart';
|
import 'generated/l10n.dart';
|
||||||
import 'models/photography_value.dart';
|
import 'models/photography_value.dart';
|
||||||
import 'res/dimens.dart';
|
|
||||||
import 'res/theme.dart';
|
import 'res/theme.dart';
|
||||||
import 'screens/metering/metering_bloc.dart';
|
import 'screens/metering/metering_bloc.dart';
|
||||||
import 'screens/metering/metering_screen.dart';
|
import 'screens/metering/metering_screen.dart';
|
||||||
|
@ -28,10 +26,7 @@ class Application extends StatefulWidget {
|
||||||
State<Application> createState() => _ApplicationState();
|
State<Application> createState() => _ApplicationState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ApplicationState extends State<Application> with TickerProviderStateMixin {
|
class _ApplicationState extends State<Application> {
|
||||||
late final AnimationController _animationController;
|
|
||||||
late final _settingsRouteObserver = _SettingsRouteObserver(onPush: _onSettingsPush, onPop: _onSettingsPop);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
|
@ -43,20 +38,6 @@ class _ApplicationState extends State<Application> with TickerProviderStateMixin
|
||||||
systemNavigationBarIconBrightness: Brightness.dark,
|
systemNavigationBarIconBrightness: Brightness.dark,
|
||||||
);
|
);
|
||||||
SystemChrome.setSystemUIOverlayStyle(mySystemTheme);
|
SystemChrome.setSystemUIOverlayStyle(mySystemTheme);
|
||||||
// 0 - collapsed
|
|
||||||
// 1 - expanded
|
|
||||||
_animationController = AnimationController(
|
|
||||||
value: 0,
|
|
||||||
duration: Dimens.durationM,
|
|
||||||
reverseDuration: Dimens.durationSM,
|
|
||||||
vsync: this,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_animationController.dispose();
|
|
||||||
super.dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -71,7 +52,6 @@ class _ApplicationState extends State<Application> with TickerProviderStateMixin
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
colorScheme: lightColorScheme,
|
colorScheme: lightColorScheme,
|
||||||
),
|
),
|
||||||
navigatorObservers: [_settingsRouteObserver],
|
|
||||||
localizationsDelegates: const [
|
localizationsDelegates: const [
|
||||||
S.delegate,
|
S.delegate,
|
||||||
GlobalMaterialLocalizations.delegate,
|
GlobalMaterialLocalizations.delegate,
|
||||||
|
@ -79,9 +59,13 @@ class _ApplicationState extends State<Application> with TickerProviderStateMixin
|
||||||
GlobalCupertinoLocalizations.delegate,
|
GlobalCupertinoLocalizations.delegate,
|
||||||
],
|
],
|
||||||
supportedLocales: S.delegate.supportedLocales,
|
supportedLocales: S.delegate.supportedLocales,
|
||||||
home: MeteringScreen(animationController: _animationController),
|
builder: (context, child) => MediaQuery(
|
||||||
|
data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
|
||||||
|
child: child!,
|
||||||
|
),
|
||||||
|
home: const MeteringScreen(),
|
||||||
routes: {
|
routes: {
|
||||||
"metering": (context) => MeteringScreen(animationController: _animationController),
|
"metering": (context) => const MeteringScreen(),
|
||||||
"settings": (context) => const SettingsScreen(),
|
"settings": (context) => const SettingsScreen(),
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@ -89,44 +73,4 @@ class _ApplicationState extends State<Application> with TickerProviderStateMixin
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _onSettingsPush() {
|
|
||||||
if (!_animationController.isAnimating && _animationController.status != AnimationStatus.completed) {
|
|
||||||
_animationController.forward();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _onSettingsPop() {
|
|
||||||
Future.delayed(Dimens.durationM).then((_) {
|
|
||||||
if (!_animationController.isAnimating && _animationController.status != AnimationStatus.dismissed) {
|
|
||||||
_animationController.reverse();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _SettingsRouteObserver extends RouteObserver<SettingsPageRouteBuilder> {
|
|
||||||
final VoidCallback onPush;
|
|
||||||
final VoidCallback onPop;
|
|
||||||
|
|
||||||
_SettingsRouteObserver({
|
|
||||||
required this.onPush,
|
|
||||||
required this.onPop,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
void didPush(Route<dynamic> route, Route<dynamic>? previousRoute) {
|
|
||||||
super.didPush(route, previousRoute);
|
|
||||||
if (route is SettingsPageRouteBuilder) {
|
|
||||||
onPush();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void didPop(Route<dynamic> route, Route<dynamic>? previousRoute) {
|
|
||||||
super.didPop(route, previousRoute);
|
|
||||||
if (previousRoute is PageRoute && route is SettingsPageRouteBuilder) {
|
|
||||||
onPop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,101 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:lightmeter/res/dimens.dart';
|
|
||||||
|
|
||||||
class MeteringScreenAnimatedSurface extends _AnimatedSurface {
|
|
||||||
MeteringScreenAnimatedSurface.top({
|
|
||||||
required super.controller,
|
|
||||||
required super.areaHeight,
|
|
||||||
required super.overflowSize,
|
|
||||||
required super.child,
|
|
||||||
}) : super(
|
|
||||||
alignment: Alignment.topCenter,
|
|
||||||
borderRadiusBegin: const BorderRadius.only(
|
|
||||||
bottomLeft: Radius.circular(Dimens.borderRadiusL),
|
|
||||||
bottomRight: Radius.circular(Dimens.borderRadiusL),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
MeteringScreenAnimatedSurface.bottom({
|
|
||||||
required super.controller,
|
|
||||||
required super.areaHeight,
|
|
||||||
required super.overflowSize,
|
|
||||||
required super.child,
|
|
||||||
}) : super(
|
|
||||||
alignment: Alignment.bottomCenter,
|
|
||||||
borderRadiusBegin: const BorderRadius.only(
|
|
||||||
topLeft: Radius.circular(Dimens.borderRadiusL),
|
|
||||||
topRight: Radius.circular(Dimens.borderRadiusL),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class _AnimatedSurface extends StatelessWidget {
|
|
||||||
final AnimationController controller;
|
|
||||||
final Alignment alignment;
|
|
||||||
final double areaHeight;
|
|
||||||
final double overflowSize;
|
|
||||||
final Widget child;
|
|
||||||
|
|
||||||
final Animation<BorderRadius?> _borderRadiusAnimation;
|
|
||||||
final Animation<double> _childOpacityAnimation;
|
|
||||||
final Animation<double> _overflowHeightAnimation;
|
|
||||||
|
|
||||||
_AnimatedSurface({
|
|
||||||
required this.controller,
|
|
||||||
required this.alignment,
|
|
||||||
required BorderRadius borderRadiusBegin,
|
|
||||||
required this.areaHeight,
|
|
||||||
required this.overflowSize,
|
|
||||||
required this.child,
|
|
||||||
}) : _borderRadiusAnimation = BorderRadiusTween(
|
|
||||||
begin: borderRadiusBegin,
|
|
||||||
end: BorderRadius.zero,
|
|
||||||
).animate(
|
|
||||||
CurvedAnimation(
|
|
||||||
parent: controller,
|
|
||||||
curve: const Interval(0.4, 1.0, curve: Curves.linear),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
_childOpacityAnimation = Tween<double>(
|
|
||||||
begin: 1,
|
|
||||||
end: 0,
|
|
||||||
).animate(
|
|
||||||
CurvedAnimation(
|
|
||||||
parent: controller,
|
|
||||||
curve: const Interval(0.0, 0.4, curve: Curves.linear),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
_overflowHeightAnimation = Tween<double>(
|
|
||||||
begin: 0,
|
|
||||||
end: overflowSize,
|
|
||||||
).animate(
|
|
||||||
CurvedAnimation(
|
|
||||||
parent: controller,
|
|
||||||
curve: const Interval(0.0, 1.0, curve: Curves.linear),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return AnimatedBuilder(
|
|
||||||
animation: controller,
|
|
||||||
child: child,
|
|
||||||
builder: (context, child) => SizedBox(
|
|
||||||
height: areaHeight + _overflowHeightAnimation.value,
|
|
||||||
child: ClipRRect(
|
|
||||||
borderRadius: _borderRadiusAnimation.value,
|
|
||||||
child: ColoredBox(
|
|
||||||
color: Theme.of(context).colorScheme.surface,
|
|
||||||
child: Align(
|
|
||||||
alignment: alignment,
|
|
||||||
child: Opacity(
|
|
||||||
opacity: _childOpacityAnimation.value,
|
|
||||||
child: child,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -51,7 +51,7 @@ class _ReadingValueBuilder extends StatelessWidget {
|
||||||
reading.label,
|
reading.label,
|
||||||
style: textTheme.labelMedium?.copyWith(color: Theme.of(context).colorScheme.onPrimaryContainer),
|
style: textTheme.labelMedium?.copyWith(color: Theme.of(context).colorScheme.onPrimaryContainer),
|
||||||
),
|
),
|
||||||
const SizedBox(height: Dimens.grid4),
|
const SizedBox(height: Dimens.grid8),
|
||||||
Text(
|
Text(
|
||||||
reading.value,
|
reading.value,
|
||||||
style: textTheme.bodyLarge?.copyWith(color: Theme.of(context).colorScheme.onPrimaryContainer),
|
style: textTheme.bodyLarge?.copyWith(color: Theme.of(context).colorScheme.onPrimaryContainer),
|
||||||
|
|
|
@ -12,8 +12,6 @@ import 'components/reading_container.dart';
|
||||||
import 'models/reading_value.dart';
|
import 'models/reading_value.dart';
|
||||||
|
|
||||||
class MeteringTopBar extends StatelessWidget {
|
class MeteringTopBar extends StatelessWidget {
|
||||||
static const _columnsCount = 3;
|
|
||||||
|
|
||||||
final ExposurePair? fastest;
|
final ExposurePair? fastest;
|
||||||
final ExposurePair? slowest;
|
final ExposurePair? slowest;
|
||||||
final double ev;
|
final double ev;
|
||||||
|
@ -35,8 +33,6 @@ class MeteringTopBar extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final columnWidth =
|
|
||||||
(MediaQuery.of(context).size.width - Dimens.paddingM * 2 - Dimens.grid16 * (_columnsCount - 1)) / 3;
|
|
||||||
return ClipRRect(
|
return ClipRRect(
|
||||||
borderRadius: const BorderRadius.only(
|
borderRadius: const BorderRadius.only(
|
||||||
bottomLeft: Radius.circular(Dimens.borderRadiusL),
|
bottomLeft: Radius.circular(Dimens.borderRadiusL),
|
||||||
|
@ -50,96 +46,88 @@ class MeteringTopBar extends StatelessWidget {
|
||||||
bottom: false,
|
bottom: false,
|
||||||
child: MediaQuery(
|
child: MediaQuery(
|
||||||
data: MediaQuery.of(context),
|
data: MediaQuery.of(context),
|
||||||
child: Row(
|
child: IntrinsicHeight(
|
||||||
mainAxisSize: MainAxisSize.min,
|
child: Row(
|
||||||
children: [
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
Expanded(
|
mainAxisSize: MainAxisSize.min,
|
||||||
child: Column(
|
children: [
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
Expanded(
|
||||||
children: [
|
child: Column(
|
||||||
SizedBox(
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
height: columnWidth / 3 * 4,
|
children: [
|
||||||
child: ReadingContainer(
|
Expanded(
|
||||||
values: [
|
child: ReadingContainer(
|
||||||
ReadingValue(
|
values: [
|
||||||
label: S.of(context).fastestExposurePair,
|
ReadingValue(
|
||||||
value: fastest != null
|
label: S.of(context).fastestExposurePair,
|
||||||
? '${fastest!.aperture.toString()} - ${fastest!.shutterSpeed.toString()}'
|
value: fastest != null
|
||||||
: 'N/A',
|
? '${fastest!.aperture.toString()} - ${fastest!.shutterSpeed.toString()}'
|
||||||
),
|
: 'N/A',
|
||||||
ReadingValue(
|
),
|
||||||
label: S.of(context).slowestExposurePair,
|
ReadingValue(
|
||||||
value: fastest != null
|
label: S.of(context).slowestExposurePair,
|
||||||
? '${slowest!.aperture.toString()} - ${slowest!.shutterSpeed.toString()}'
|
value: fastest != null
|
||||||
: 'N/A',
|
? '${slowest!.aperture.toString()} - ${slowest!.shutterSpeed.toString()}'
|
||||||
),
|
: 'N/A',
|
||||||
],
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
const _InnerPadding(),
|
||||||
const _InnerPadding(),
|
Row(
|
||||||
Row(
|
children: [
|
||||||
children: [
|
Expanded(
|
||||||
SizedBox(
|
child: _AnimatedDialogPicker(
|
||||||
width: columnWidth,
|
title: S.of(context).iso,
|
||||||
child: ReadingContainer.singleValue(
|
subtitle: S.of(context).filmSpeed,
|
||||||
value: ReadingValue(
|
selectedValue: iso,
|
||||||
label: 'EV',
|
values: isoValues,
|
||||||
value: ev.toStringAsFixed(1),
|
itemTitleBuilder: (_, value) => Text(value.value.toString()),
|
||||||
|
// using ascending order, because increase in film speed rises EV
|
||||||
|
evDifferenceBuilder: (selected, other) => selected.toStringDifference(other),
|
||||||
|
onChanged: onIsoChanged,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
const _InnerPadding(),
|
||||||
const _InnerPadding(),
|
Expanded(
|
||||||
SizedBox(
|
child: _AnimatedDialogPicker(
|
||||||
width: columnWidth,
|
title: S.of(context).nd,
|
||||||
child: _AnimatedDialogPicker(
|
subtitle: S.of(context).ndFilterFactor,
|
||||||
title: S.of(context).iso,
|
selectedValue: nd,
|
||||||
subtitle: S.of(context).filmSpeed,
|
values: ndValues,
|
||||||
selectedValue: iso,
|
itemTitleBuilder: (_, value) => Text(
|
||||||
values: isoValues,
|
value.value == 0 ? S.of(context).none : value.value.toString(),
|
||||||
itemTitleBuilder: (_, value) => Text(value.value.toString()),
|
),
|
||||||
// using ascending order, because increase in film speed rises EV
|
// using descending order, because ND filter darkens image & lowers EV
|
||||||
evDifferenceBuilder: (selected, other) => selected.toStringDifference(other),
|
evDifferenceBuilder: (selected, other) => other.toStringDifference(selected),
|
||||||
onChanged: onIsoChanged,
|
onChanged: onNdChanged,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const _InnerPadding(),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
AnimatedDialog(
|
||||||
|
openedSize: Size(
|
||||||
|
MediaQuery.of(context).size.width - Dimens.paddingM * 2,
|
||||||
|
(MediaQuery.of(context).size.width - Dimens.paddingM * 2) / 3 * 4,
|
||||||
),
|
),
|
||||||
],
|
child: const AspectRatio(
|
||||||
)
|
aspectRatio: 3 / 4,
|
||||||
],
|
child: ColoredBox(color: Colors.black),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
const _InnerPadding(),
|
),
|
||||||
SizedBox(
|
|
||||||
width: columnWidth,
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: [
|
|
||||||
AnimatedDialog(
|
|
||||||
openedSize: Size(
|
|
||||||
MediaQuery.of(context).size.width - Dimens.paddingM * 2,
|
|
||||||
(MediaQuery.of(context).size.width - Dimens.paddingM * 2) / 3 * 4,
|
|
||||||
),
|
|
||||||
child: const AspectRatio(
|
|
||||||
aspectRatio: 3 / 4,
|
|
||||||
child: ColoredBox(color: Colors.black),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const _InnerPadding(),
|
|
||||||
_AnimatedDialogPicker(
|
|
||||||
title: S.of(context).nd,
|
|
||||||
subtitle: S.of(context).ndFilterFactor,
|
|
||||||
selectedValue: nd,
|
|
||||||
values: ndValues,
|
|
||||||
itemTitleBuilder: (_, value) => Text(
|
|
||||||
value.value == 0 ? S.of(context).none : value.value.toString(),
|
|
||||||
),
|
|
||||||
// using descending order, because ND filter darkens image & lowers EV
|
|
||||||
evDifferenceBuilder: (selected, other) => other.toStringDifference(selected),
|
|
||||||
onChanged: onNdChanged,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -150,7 +138,7 @@ class MeteringTopBar extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _InnerPadding extends SizedBox {
|
class _InnerPadding extends SizedBox {
|
||||||
const _InnerPadding() : super(height: Dimens.grid16, width: Dimens.grid16);
|
const _InnerPadding() : super(height: Dimens.grid8, width: Dimens.grid8);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AnimatedDialogPicker<T extends PhotographyValue> extends StatelessWidget {
|
class _AnimatedDialogPicker<T extends PhotographyValue> extends StatelessWidget {
|
||||||
|
|
|
@ -2,9 +2,8 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:lightmeter/models/photography_value.dart';
|
import 'package:lightmeter/models/photography_value.dart';
|
||||||
import 'package:lightmeter/res/dimens.dart';
|
import 'package:lightmeter/res/dimens.dart';
|
||||||
import 'package:lightmeter/screens/settings/settings_page_route_builder.dart';
|
import 'package:lightmeter/screens/settings/settings_screen.dart';
|
||||||
|
|
||||||
import 'components/animated_surface/animated_surface.dart';
|
|
||||||
import 'components/bottom_controls/bottom_controls.dart';
|
import 'components/bottom_controls/bottom_controls.dart';
|
||||||
import 'components/exposure_pairs_list/exposure_pairs_list.dart';
|
import 'components/exposure_pairs_list/exposure_pairs_list.dart';
|
||||||
import 'components/topbar/topbar.dart';
|
import 'components/topbar/topbar.dart';
|
||||||
|
@ -13,37 +12,13 @@ import 'metering_event.dart';
|
||||||
import 'metering_state.dart';
|
import 'metering_state.dart';
|
||||||
|
|
||||||
class MeteringScreen extends StatefulWidget {
|
class MeteringScreen extends StatefulWidget {
|
||||||
final AnimationController animationController;
|
const MeteringScreen({super.key});
|
||||||
|
|
||||||
const MeteringScreen({required this.animationController, super.key});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<MeteringScreen> createState() => _MeteringScreenState();
|
State<MeteringScreen> createState() => _MeteringScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MeteringScreenState extends State<MeteringScreen> {
|
class _MeteringScreenState extends State<MeteringScreen> {
|
||||||
final _topBarKey = GlobalKey(debugLabel: 'TopBarKey');
|
|
||||||
final _middleAreaKey = GlobalKey(debugLabel: 'MiddleAreaKey');
|
|
||||||
final _bottomBarKey = GlobalKey(debugLabel: 'BottomBarKey');
|
|
||||||
|
|
||||||
bool _secondBuild = false;
|
|
||||||
late double _topBarHeight;
|
|
||||||
late double _middleAreaHeight;
|
|
||||||
late double _bottomBarHeight;
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
_topBarHeight = _getHeight(_topBarKey);
|
|
||||||
_middleAreaHeight = _getHeight(_middleAreaKey);
|
|
||||||
_bottomBarHeight = _getHeight(_bottomBarKey);
|
|
||||||
setState(() {
|
|
||||||
_secondBuild = true;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
|
@ -60,50 +35,20 @@ class _MeteringScreenState extends State<MeteringScreen> {
|
||||||
children: [
|
children: [
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
if (_secondBuild) SizedBox(height: _topBarHeight) else _topBar(state),
|
_topBar(state),
|
||||||
Expanded(
|
Expanded(
|
||||||
key: _middleAreaKey,
|
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM),
|
padding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(child: ExposurePairsList(state.exposurePairs)),
|
||||||
flex: 2,
|
|
||||||
child: ExposurePairsList(state.exposurePairs),
|
|
||||||
),
|
|
||||||
const SizedBox(width: Dimens.grid16),
|
|
||||||
const Spacer()
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (_secondBuild) SizedBox(height: _bottomBarHeight) else _bottomBar(),
|
_bottomBar(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (_secondBuild)
|
|
||||||
Positioned(
|
|
||||||
left: 0,
|
|
||||||
top: 0,
|
|
||||||
right: 0,
|
|
||||||
child: MeteringScreenAnimatedSurface.top(
|
|
||||||
controller: widget.animationController,
|
|
||||||
areaHeight: _topBarHeight,
|
|
||||||
overflowSize: _middleAreaHeight / 2,
|
|
||||||
child: _topBar(state),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (_secondBuild)
|
|
||||||
Positioned(
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
bottom: 0,
|
|
||||||
child: MeteringScreenAnimatedSurface.bottom(
|
|
||||||
controller: widget.animationController,
|
|
||||||
areaHeight: _bottomBarHeight,
|
|
||||||
overflowSize: _middleAreaHeight / 2,
|
|
||||||
child: _bottomBar(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -113,7 +58,6 @@ class _MeteringScreenState extends State<MeteringScreen> {
|
||||||
|
|
||||||
Widget _topBar(MeteringState state) {
|
Widget _topBar(MeteringState state) {
|
||||||
return MeteringTopBar(
|
return MeteringTopBar(
|
||||||
key: _topBarKey,
|
|
||||||
fastest: state.fastest,
|
fastest: state.fastest,
|
||||||
slowest: state.slowest,
|
slowest: state.slowest,
|
||||||
ev: state.ev,
|
ev: state.ev,
|
||||||
|
@ -126,14 +70,11 @@ class _MeteringScreenState extends State<MeteringScreen> {
|
||||||
|
|
||||||
Widget _bottomBar() {
|
Widget _bottomBar() {
|
||||||
return MeteringBottomControls(
|
return MeteringBottomControls(
|
||||||
key: _bottomBarKey,
|
|
||||||
onSourceChanged: () {},
|
onSourceChanged: () {},
|
||||||
onMeasure: () => context.read<MeteringBloc>().add(const MeasureEvent()),
|
onMeasure: () => context.read<MeteringBloc>().add(const MeasureEvent()),
|
||||||
onSettings: () {
|
onSettings: () {
|
||||||
Navigator.push(context, SettingsPageRouteBuilder());
|
Navigator.push(context, MaterialPageRoute(builder: (context) => const SettingsScreen()));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
double _getHeight(GlobalKey key) => key.currentContext!.size!.height;
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:lightmeter/res/dimens.dart';
|
|
||||||
import 'package:lightmeter/screens/settings/settings_screen.dart';
|
|
||||||
|
|
||||||
class SettingsPageRouteBuilder extends PageRouteBuilder<void> {
|
|
||||||
SettingsPageRouteBuilder()
|
|
||||||
: super(
|
|
||||||
transitionDuration:
|
|
||||||
Dimens.durationM + Dimens.durationM, // wait for `MeteringScreenAnimatedSurface`s to expand
|
|
||||||
reverseTransitionDuration: Dimens.durationM,
|
|
||||||
pageBuilder: (context, animation, secondaryAnimation) => const SettingsScreen(),
|
|
||||||
transitionsBuilder: (context, animation, secondaryAnimation, child) {
|
|
||||||
final didPop = !(animation.value != 0.0 && secondaryAnimation.value == 0.0);
|
|
||||||
final tween = Tween(begin: 0.0, end: 1.0);
|
|
||||||
late Interval interval;
|
|
||||||
if (didPop) {
|
|
||||||
interval = const Interval(
|
|
||||||
0,
|
|
||||||
1.0,
|
|
||||||
curve: Curves.linear,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
interval = Interval(
|
|
||||||
Dimens.durationM.inMilliseconds / (Dimens.durationM + Dimens.durationM).inMilliseconds,
|
|
||||||
1.0,
|
|
||||||
curve: Curves.linear,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
final animatable = tween.chain(CurveTween(curve: interval));
|
|
||||||
return Opacity(
|
|
||||||
opacity: (didPop ? secondaryAnimation : animation).drive(animatable).value,
|
|
||||||
child: child,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
Loading…
Reference in a new issue