mirror of
https://github.com/vodemn/m3_lightmeter.git
synced 2024-11-22 07:20:39 +00:00
Made TopBarShape
responsive
returned `TopBarShape` fixed `TopBarShape`
This commit is contained in:
parent
5eb0869aa0
commit
5bea96669d
5 changed files with 280 additions and 101 deletions
|
@ -6,4 +6,7 @@ class ExposurePair {
|
||||||
final ShutterSpeedValue shutterSpeed;
|
final ShutterSpeedValue shutterSpeed;
|
||||||
|
|
||||||
const ExposurePair(this.aperture, this.shutterSpeed);
|
const ExposurePair(this.aperture, this.shutterSpeed);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => '${aperture.toString()} - ${shutterSpeed.toString()}';
|
||||||
}
|
}
|
||||||
|
|
97
lib/screens/metering/components/topbar/shape_topbar.dart
Normal file
97
lib/screens/metering/components/topbar/shape_topbar.dart
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:lightmeter/res/dimens.dart';
|
||||||
|
|
||||||
|
class TopBarShape extends CustomPainter {
|
||||||
|
final Color color;
|
||||||
|
|
||||||
|
/// The appendix is on the left side
|
||||||
|
/// but if appendix height is negative, then we have to make a cutout
|
||||||
|
///
|
||||||
|
/// negative positive
|
||||||
|
/// | | /// | |
|
||||||
|
/// | | /// | |
|
||||||
|
/// | | /// | |
|
||||||
|
/// | | /// | |
|
||||||
|
/// \________ | /// | ________/
|
||||||
|
/// \ | /// | / ↑
|
||||||
|
/// | | /// | | | appendix height
|
||||||
|
/// \__________/ /// \__________/ ↓
|
||||||
|
///
|
||||||
|
final double appendixHeight;
|
||||||
|
final double appendixWidth;
|
||||||
|
|
||||||
|
TopBarShape({
|
||||||
|
required this.color,
|
||||||
|
required this.appendixHeight,
|
||||||
|
required this.appendixWidth,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
void paint(Canvas canvas, Size size) {
|
||||||
|
final paint = Paint()..color = color;
|
||||||
|
final path = Path();
|
||||||
|
const circularRadius = Radius.circular(Dimens.borderRadiusL);
|
||||||
|
if (appendixHeight == 0 || appendixWidth == 0) {
|
||||||
|
path.addRRect(
|
||||||
|
RRect.fromLTRBAndCorners(
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
bottomLeft: circularRadius,
|
||||||
|
bottomRight: circularRadius,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Left side with bottom corner
|
||||||
|
path.lineTo(0, size.height + appendixHeight - Dimens.borderRadiusL);
|
||||||
|
path.arcToPoint(
|
||||||
|
Offset(Dimens.borderRadiusL, size.height + appendixHeight),
|
||||||
|
radius: circularRadius,
|
||||||
|
clockwise: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Bottom side with step
|
||||||
|
final double allowedRadius = min(appendixHeight.abs() / 2, Dimens.borderRadiusL);
|
||||||
|
path.lineTo(appendixWidth - allowedRadius, size.height + appendixHeight);
|
||||||
|
|
||||||
|
final bool isCutout = appendixHeight < 0;
|
||||||
|
if (isCutout) {
|
||||||
|
path.arcToPoint(
|
||||||
|
Offset(appendixWidth, size.height + appendixHeight + allowedRadius),
|
||||||
|
radius: circularRadius,
|
||||||
|
clockwise: true,
|
||||||
|
);
|
||||||
|
path.lineTo(appendixWidth, size.height - allowedRadius);
|
||||||
|
} else {
|
||||||
|
path.arcToPoint(
|
||||||
|
Offset(appendixWidth, size.height + appendixHeight - allowedRadius),
|
||||||
|
radius: circularRadius,
|
||||||
|
clockwise: false,
|
||||||
|
);
|
||||||
|
path.lineTo(appendixWidth, size.height + allowedRadius);
|
||||||
|
}
|
||||||
|
path.arcToPoint(
|
||||||
|
Offset(appendixWidth + allowedRadius, size.height),
|
||||||
|
radius: circularRadius,
|
||||||
|
clockwise: !isCutout,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Right side with bottom corner
|
||||||
|
path.lineTo(size.width - Dimens.borderRadiusL, size.height);
|
||||||
|
path.arcToPoint(
|
||||||
|
Offset(size.width, size.height - Dimens.borderRadiusL),
|
||||||
|
radius: circularRadius,
|
||||||
|
clockwise: false,
|
||||||
|
);
|
||||||
|
path.lineTo(size.width, 0);
|
||||||
|
path.close();
|
||||||
|
}
|
||||||
|
canvas.drawPath(path, paint);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldRepaint(CustomPainter oldDelegate) => false;
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:lightmeter/platform_config.dart';
|
||||||
import 'package:lightmeter/screens/metering/ev_source/camera/bloc_camera.dart';
|
import 'package:lightmeter/screens/metering/components/topbar/shape_topbar.dart';
|
||||||
|
import 'package:lightmeter/screens/metering/components/widget_size_render.dart';
|
||||||
import 'package:lightmeter/generated/l10n.dart';
|
import 'package:lightmeter/generated/l10n.dart';
|
||||||
import 'package:lightmeter/data/models/exposure_pair.dart';
|
import 'package:lightmeter/data/models/exposure_pair.dart';
|
||||||
import 'package:lightmeter/data/models/photography_values/iso_value.dart';
|
import 'package:lightmeter/data/models/photography_values/iso_value.dart';
|
||||||
|
@ -13,7 +14,7 @@ import 'components/shared/widget_dialog_animated.dart';
|
||||||
import 'components/widget_dialog_picker.dart';
|
import 'components/widget_dialog_picker.dart';
|
||||||
import 'components/container_reading_value.dart';
|
import 'components/container_reading_value.dart';
|
||||||
|
|
||||||
class MeteringTopBar extends StatelessWidget {
|
class MeteringTopBar extends StatefulWidget {
|
||||||
final ExposurePair? fastest;
|
final ExposurePair? fastest;
|
||||||
final ExposurePair? slowest;
|
final ExposurePair? slowest;
|
||||||
final double ev;
|
final double ev;
|
||||||
|
@ -22,6 +23,8 @@ class MeteringTopBar extends StatelessWidget {
|
||||||
final ValueChanged<IsoValue> onIsoChanged;
|
final ValueChanged<IsoValue> onIsoChanged;
|
||||||
final ValueChanged<NdValue> onNdChanged;
|
final ValueChanged<NdValue> onNdChanged;
|
||||||
|
|
||||||
|
final ValueChanged<double> onCutoutLayout;
|
||||||
|
|
||||||
const MeteringTopBar({
|
const MeteringTopBar({
|
||||||
required this.fastest,
|
required this.fastest,
|
||||||
required this.slowest,
|
required this.slowest,
|
||||||
|
@ -30,29 +33,40 @@ class MeteringTopBar extends StatelessWidget {
|
||||||
required this.nd,
|
required this.nd,
|
||||||
required this.onIsoChanged,
|
required this.onIsoChanged,
|
||||||
required this.onNdChanged,
|
required this.onNdChanged,
|
||||||
|
required this.onCutoutLayout,
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<MeteringTopBar> createState() => _MeteringTopBarState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _MeteringTopBarState extends State<MeteringTopBar> {
|
||||||
|
double stepHeight = 0.0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ClipRRect(
|
return CustomPaint(
|
||||||
borderRadius: const BorderRadius.only(
|
painter: TopBarShape(
|
||||||
bottomLeft: Radius.circular(Dimens.borderRadiusL),
|
|
||||||
bottomRight: Radius.circular(Dimens.borderRadiusL),
|
|
||||||
),
|
|
||||||
child: ColoredBox(
|
|
||||||
color: Theme.of(context).colorScheme.surface,
|
color: Theme.of(context).colorScheme.surface,
|
||||||
child: Padding(
|
appendixWidth: stepHeight > 0
|
||||||
padding: const EdgeInsets.all(Dimens.paddingM),
|
? MediaQuery.of(context).size.width / 2 - Dimens.grid8 + Dimens.paddingM
|
||||||
child: SafeArea(
|
: MediaQuery.of(context).size.width / 2 + Dimens.grid8 - Dimens.paddingM,
|
||||||
bottom: false,
|
appendixHeight: stepHeight,
|
||||||
child: MediaQuery(
|
),
|
||||||
data: MediaQuery.of(context),
|
child: Padding(
|
||||||
child: Row(
|
padding: const EdgeInsets.all(Dimens.paddingM),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
child: SafeArea(
|
||||||
mainAxisSize: MainAxisSize.min,
|
bottom: false,
|
||||||
children: [
|
child: MediaQuery(
|
||||||
Expanded(
|
data: MediaQuery.of(context),
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: ReadingsContainer(
|
||||||
|
onLayout: (size) => _onReadingsLayout(size.height),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
|
@ -60,15 +74,11 @@ class MeteringTopBar extends StatelessWidget {
|
||||||
values: [
|
values: [
|
||||||
ReadingValue(
|
ReadingValue(
|
||||||
label: S.of(context).fastestExposurePair,
|
label: S.of(context).fastestExposurePair,
|
||||||
value: fastest != null
|
value: widget.fastest != null ? widget.fastest!.toString() : '-',
|
||||||
? '${fastest!.aperture.toString()} - ${fastest!.shutterSpeed.toString()}'
|
|
||||||
: '-',
|
|
||||||
),
|
),
|
||||||
ReadingValue(
|
ReadingValue(
|
||||||
label: S.of(context).slowestExposurePair,
|
label: S.of(context).slowestExposurePair,
|
||||||
value: fastest != null
|
value: widget.fastest != null ? widget.slowest!.toString() : '-',
|
||||||
? '${slowest!.aperture.toString()} - ${slowest!.shutterSpeed.toString()}'
|
|
||||||
: '-',
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -85,30 +95,16 @@ class MeteringTopBar extends StatelessWidget {
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: _AnimatedDialogPicker(
|
child: _IsoValueTile(
|
||||||
title: S.of(context).iso,
|
value: widget.iso,
|
||||||
subtitle: S.of(context).filmSpeed,
|
onChanged: widget.onIsoChanged,
|
||||||
selectedValue: iso,
|
|
||||||
values: isoValues,
|
|
||||||
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(
|
Expanded(
|
||||||
child: _AnimatedDialogPicker(
|
child: _NdValueTile(
|
||||||
title: S.of(context).nd,
|
value: widget.nd,
|
||||||
subtitle: S.of(context).ndFilterFactor,
|
onChanged: widget.onNdChanged,
|
||||||
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,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -116,33 +112,76 @@ class MeteringTopBar extends StatelessWidget {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const _InnerPadding(),
|
),
|
||||||
Expanded(
|
const _InnerPadding(),
|
||||||
child: AnimatedDialog(
|
const Expanded(
|
||||||
openedSize: Size(
|
child: ClipRRect(
|
||||||
MediaQuery.of(context).size.width - Dimens.paddingM * 2,
|
borderRadius: BorderRadius.all(Radius.circular(Dimens.borderRadiusM)),
|
||||||
(MediaQuery.of(context).size.width - Dimens.paddingM * 2) / 3 * 4,
|
child: CameraView(),
|
||||||
),
|
|
||||||
child: BlocProvider.value(
|
|
||||||
value: context.read<CameraBloc>(),
|
|
||||||
child: const CameraView(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _onReadingsLayout(double readingsSectionHeight) {
|
||||||
|
stepHeight = readingsSectionHeight -
|
||||||
|
((MediaQuery.of(context).size.width - Dimens.grid8 - 2 * Dimens.paddingM) / 2) /
|
||||||
|
PlatformConfig.cameraPreviewAspectRatio;
|
||||||
|
widget.onCutoutLayout(stepHeight);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _InnerPadding extends SizedBox {
|
class _InnerPadding extends SizedBox {
|
||||||
const _InnerPadding() : super(height: Dimens.grid8, width: Dimens.grid8);
|
const _InnerPadding() : super(height: Dimens.grid8, width: Dimens.grid8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _IsoValueTile extends StatelessWidget {
|
||||||
|
final IsoValue value;
|
||||||
|
final ValueChanged<IsoValue> onChanged;
|
||||||
|
|
||||||
|
const _IsoValueTile({required this.value, required this.onChanged});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return _AnimatedDialogPicker<IsoValue>(
|
||||||
|
title: S.of(context).iso,
|
||||||
|
subtitle: S.of(context).filmSpeed,
|
||||||
|
selectedValue: value,
|
||||||
|
values: isoValues,
|
||||||
|
itemTitleBuilder: (_, value) => Text(value.value.toString()),
|
||||||
|
// using ascending order, because increase in film speed rises EV
|
||||||
|
evDifferenceBuilder: (selected, other) => selected.toStringDifference(other),
|
||||||
|
onChanged: onChanged,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _NdValueTile extends StatelessWidget {
|
||||||
|
final NdValue value;
|
||||||
|
final ValueChanged<NdValue> onChanged;
|
||||||
|
|
||||||
|
const _NdValueTile({required this.value, required this.onChanged});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return _AnimatedDialogPicker<NdValue>(
|
||||||
|
title: S.of(context).nd,
|
||||||
|
subtitle: S.of(context).ndFilterFactor,
|
||||||
|
selectedValue: value,
|
||||||
|
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: onChanged,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _AnimatedDialogPicker<T extends PhotographyValue> extends StatelessWidget {
|
class _AnimatedDialogPicker<T extends PhotographyValue> extends StatelessWidget {
|
||||||
final _key = GlobalKey<AnimatedDialogState>();
|
final _key = GlobalKey<AnimatedDialogState>();
|
||||||
final String title;
|
final String title;
|
||||||
|
|
32
lib/screens/metering/components/widget_size_render.dart
Normal file
32
lib/screens/metering/components/widget_size_render.dart
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/rendering.dart';
|
||||||
|
|
||||||
|
class ReadingsContainer extends SingleChildRenderObjectWidget {
|
||||||
|
final ValueChanged<Size>? onLayout;
|
||||||
|
|
||||||
|
const ReadingsContainer({
|
||||||
|
super.key,
|
||||||
|
super.child,
|
||||||
|
this.onLayout,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
RenderReadingsContainer createRenderObject(BuildContext context) => RenderReadingsContainer(onLayout: onLayout);
|
||||||
|
}
|
||||||
|
|
||||||
|
class RenderReadingsContainer extends RenderProxyBox {
|
||||||
|
final ValueChanged<Size>? onLayout;
|
||||||
|
|
||||||
|
RenderReadingsContainer({this.onLayout});
|
||||||
|
|
||||||
|
@override
|
||||||
|
void performLayout() {
|
||||||
|
if (child != null) {
|
||||||
|
child!.layout(constraints, parentUsesSize: true);
|
||||||
|
size = child!.size;
|
||||||
|
} else {
|
||||||
|
size = computeSizeForNoChild(constraints);
|
||||||
|
}
|
||||||
|
onLayout?.call(size);
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,6 +21,8 @@ class MeteringScreen extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _MeteringScreenState extends State<MeteringScreen> {
|
class _MeteringScreenState extends State<MeteringScreen> {
|
||||||
|
double topBarOverflow = 0.0;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void didChangeDependencies() {
|
void didChangeDependencies() {
|
||||||
super.didChangeDependencies();
|
super.didChangeDependencies();
|
||||||
|
@ -37,31 +39,59 @@ class _MeteringScreenState extends State<MeteringScreen> {
|
||||||
children: [
|
children: [
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
_topBar(state),
|
MeteringTopBar(
|
||||||
|
fastest: state.fastest,
|
||||||
|
slowest: state.slowest,
|
||||||
|
ev: state.ev,
|
||||||
|
iso: state.iso,
|
||||||
|
nd: state.nd,
|
||||||
|
onIsoChanged: (value) => context.read<MeteringBloc>().add(IsoChangedEvent(value)),
|
||||||
|
onNdChanged: (value) => context.read<MeteringBloc>().add(NdChangedEvent(value)),
|
||||||
|
onCutoutLayout: (value) => topBarOverflow = value,
|
||||||
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Padding(
|
child: LayoutBuilder(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM),
|
builder: (context, constraints) => OverflowBox(
|
||||||
child: Row(
|
alignment: Alignment.bottomCenter,
|
||||||
children: [
|
maxHeight: constraints.maxHeight + topBarOverflow.abs(),
|
||||||
Expanded(child: ExposurePairsList(state.exposurePairs)),
|
maxWidth: constraints.maxWidth,
|
||||||
const SizedBox(width: Dimens.grid8),
|
child: Padding(
|
||||||
Expanded(
|
padding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM),
|
||||||
child: Padding(
|
child: Row(
|
||||||
padding: const EdgeInsets.symmetric(vertical: Dimens.paddingM),
|
children: [
|
||||||
child: Column(
|
Expanded(
|
||||||
children: const [
|
child: Padding(
|
||||||
Expanded(child: CameraExposureSlider()),
|
padding: topBarOverflow >= 0 ? EdgeInsets.only(top: topBarOverflow) : EdgeInsets.zero,
|
||||||
SizedBox(height: Dimens.grid24),
|
child: ExposurePairsList(state.exposurePairs),
|
||||||
CameraZoomSlider(),
|
),
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
const SizedBox(width: Dimens.grid8),
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: Dimens.paddingM).add(
|
||||||
|
topBarOverflow <= 0 ? EdgeInsets.only(top: -topBarOverflow) : EdgeInsets.zero),
|
||||||
|
child: Column(
|
||||||
|
children: const [
|
||||||
|
Expanded(child: CameraExposureSlider()),
|
||||||
|
SizedBox(height: Dimens.grid24),
|
||||||
|
CameraZoomSlider(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
_bottomBar(),
|
MeteringBottomControls(
|
||||||
|
onSourceChanged: () {},
|
||||||
|
onMeasure: () => context.read<MeteringBloc>().add(const MeasureEvent()),
|
||||||
|
onSettings: () {
|
||||||
|
Navigator.push(context, MaterialPageRoute(builder: (context) => const SettingsScreen()));
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -70,26 +100,4 @@ class _MeteringScreenState extends State<MeteringScreen> {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _topBar(MeteringState state) {
|
|
||||||
return MeteringTopBar(
|
|
||||||
fastest: state.fastest,
|
|
||||||
slowest: state.slowest,
|
|
||||||
ev: state.ev,
|
|
||||||
iso: state.iso,
|
|
||||||
nd: state.nd,
|
|
||||||
onIsoChanged: (value) => context.read<MeteringBloc>().add(IsoChangedEvent(value)),
|
|
||||||
onNdChanged: (value) => context.read<MeteringBloc>().add(NdChangedEvent(value)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _bottomBar() {
|
|
||||||
return MeteringBottomControls(
|
|
||||||
onSourceChanged: () {},
|
|
||||||
onMeasure: () => context.read<MeteringBloc>().add(const MeasureEvent()),
|
|
||||||
onSettings: () {
|
|
||||||
Navigator.push(context, MaterialPageRoute(builder: (context) => const SettingsScreen()));
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue