made zoom slider vertical & added more ticks to ruler

This commit is contained in:
Vadim 2024-03-21 23:28:29 +01:00
parent bfd0bfe531
commit 26175c2c3e
6 changed files with 137 additions and 79 deletions

View file

@ -38,7 +38,7 @@ class Dimens {
// `CenteredSlider` // `CenteredSlider`
static const double cameraSliderTrackHeight = grid4; static const double cameraSliderTrackHeight = grid4;
static const double cameraSliderTrackRadius = cameraSliderTrackHeight / 2; static const double cameraSliderTrackRadius = cameraSliderTrackHeight / 2;
static const double cameraSliderHandleSize = 32; static const double cameraSliderHandleSize = 24;
static const double cameraSliderHandleIconSize = cameraSliderHandleSize * 2 / 3; static const double cameraSliderHandleIconSize = cameraSliderHandleSize * 2 / 3;
// Dialog // Dialog

View file

@ -1,7 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/screens/shared/ruler_slider/widget_slider_ruler.dart';
import 'package:lightmeter/screens/shared/centered_slider/widget_slider_centered.dart';
import 'package:lightmeter/utils/to_string_signed.dart'; import 'package:lightmeter/utils/to_string_signed.dart';
class ExposureOffsetSlider extends StatelessWidget { class ExposureOffsetSlider extends StatelessWidget {
@ -26,68 +25,15 @@ class ExposureOffsetSlider extends StatelessWidget {
tooltip: S.of(context).tooltipResetToZero, tooltip: S.of(context).tooltipResetToZero,
), ),
Expanded( Expanded(
child: Row( child: RulerSlider(
mainAxisAlignment: MainAxisAlignment.center, icon: Icons.light_mode,
children: [ range: range,
Padding(
padding: const EdgeInsets.symmetric(vertical: Dimens.grid8),
child: _Ruler(
range.start,
range.end,
),
),
CenteredSlider(
isVertical: true,
icon: const Icon(Icons.light_mode),
value: value, value: value,
min: range.start,
max: range.end,
onChanged: onChanged, onChanged: onChanged,
), rulerValueAdapter: (value) => value.toStringSignedAsFixed(0),
],
), ),
), ),
], ],
); );
} }
} }
class _Ruler extends StatelessWidget {
final double min;
final double max;
const _Ruler(this.min, this.max);
@override
Widget build(BuildContext context) {
return Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: List.generate(
(max - min + 1).toInt(),
(index) {
final bool showValue = index % 2 == 0.0 || index == 0.0;
return Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
if (showValue)
Text(
(index + min).toStringSignedAsFixed(0),
style: Theme.of(context).textTheme.bodyLarge,
),
const SizedBox(width: Dimens.grid8),
ColoredBox(
color: Theme.of(context).colorScheme.onBackground,
child: SizedBox(
height: 1,
width: showValue ? Dimens.grid16 : Dimens.grid8,
),
),
const SizedBox(width: Dimens.grid8),
],
);
},
).reversed.toList(),
);
}
}

View file

@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lightmeter/screens/shared/centered_slider/widget_slider_centered.dart'; import 'package:lightmeter/screens/shared/ruler_slider/widget_slider_ruler.dart';
class ZoomSlider extends StatelessWidget { class ZoomSlider extends StatelessWidget {
final RangeValues range; final RangeValues range;
@ -15,12 +15,22 @@ class ZoomSlider extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return CenteredSlider( return Column(
icon: const Icon(Icons.search), children: [
const IconButton(
icon: Icon(Icons.lock_open),
onPressed: null,
),
Expanded(
child: RulerSlider(
icon: Icons.search,
range: range,
value: value, value: value,
min: range.start,
max: range.end,
onChanged: onChanged, onChanged: onChanged,
rulerValueAdapter: (value) => '${value.toStringAsFixed(0)}x',
),
),
],
); );
} }
} }

View file

@ -1,5 +1,4 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/metering/components/camera_container/components/camera_controls/components/exposure_offset_slider/widget_slider_exposure_offset.dart'; import 'package:lightmeter/screens/metering/components/camera_container/components/camera_controls/components/exposure_offset_slider/widget_slider_exposure_offset.dart';
import 'package:lightmeter/screens/metering/components/camera_container/components/camera_controls/components/zoom_slider/widget_slider_zoom.dart'; import 'package:lightmeter/screens/metering/components/camera_container/components/camera_controls/components/zoom_slider/widget_slider_zoom.dart';
@ -25,16 +24,14 @@ class CameraControls extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Column( return Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [ children: [
Expanded( ExposureOffsetSlider(
child: ExposureOffsetSlider(
range: exposureOffsetRange, range: exposureOffsetRange,
value: exposureOffsetValue, value: exposureOffsetValue,
onChanged: onExposureOffsetChanged, onChanged: onExposureOffsetChanged,
), ),
),
const SizedBox(height: Dimens.grid24),
ZoomSlider( ZoomSlider(
range: zoomRange, range: zoomRange,
value: zoomValue, value: zoomValue,

View file

@ -157,7 +157,12 @@ class _CameraControlsBuilder extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Padding( return Padding(
padding: const EdgeInsets.symmetric(vertical: Dimens.paddingM), padding: const EdgeInsets.fromLTRB(
Dimens.paddingL,
Dimens.paddingM,
0,
Dimens.paddingL,
),
child: BlocBuilder<CameraContainerBloc, CameraContainerState>( child: BlocBuilder<CameraContainerBloc, CameraContainerState>(
builder: (context, state) { builder: (context, state) {
late final Widget child; late final Widget child;

View file

@ -0,0 +1,100 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/shared/centered_slider/widget_slider_centered.dart';
class RulerSlider extends StatelessWidget {
final IconData icon;
final RangeValues range;
final double value;
final ValueChanged<double> onChanged;
final String Function(double value) rulerValueAdapter;
const RulerSlider({
required this.icon,
required this.range,
required this.value,
required this.onChanged,
required this.rulerValueAdapter,
super.key,
});
@override
Widget build(BuildContext context) {
return Row(
children: [
_Ruler(
range.start,
range.end,
rulerValueAdapter,
),
CenteredSlider(
isVertical: true,
icon: Icon(icon),
value: value,
min: range.start,
max: range.end,
onChanged: onChanged,
),
],
);
}
}
class _Ruler extends StatelessWidget {
final double min;
final double max;
final String Function(double value) rulerValueAdapter;
late final int mainTicksCount = (max - min + 1).toInt();
late final int itemsCount = mainTicksCount * 2 - 1;
_Ruler(
this.min,
this.max,
this.rulerValueAdapter,
);
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
final bool showAllMainTicks = Dimens.cameraSliderHandleSize * mainTicksCount <= constraints.maxHeight;
return Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: List.generate(
itemsCount,
(index) {
final bool isMainTick = index % 2 == 0.0;
if (!showAllMainTicks && !isMainTick) {
return const SizedBox();
}
final bool showValue = (index % (showAllMainTicks ? 2 : 4) == 0.0);
return SizedBox(
height: index == itemsCount - 1 || showValue ? Dimens.cameraSliderHandleSize : 1,
child: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
if (showValue)
Text(
rulerValueAdapter(index / 2 + min),
style: Theme.of(context).textTheme.bodySmall,
),
const SizedBox(width: Dimens.grid4),
ColoredBox(
color: Theme.of(context).colorScheme.onBackground,
child: SizedBox(
height: 1,
width: isMainTick ? Dimens.grid8 : Dimens.grid4,
),
),
const SizedBox(width: Dimens.grid4),
],
),
);
},
).reversed.toList(),
);
},
);
}
}