mirror of
https://github.com/vodemn/m3_lightmeter.git
synced 2024-11-22 07:20:39 +00:00
made zoom slider vertical & added more ticks to ruler
This commit is contained in:
parent
bfd0bfe531
commit
26175c2c3e
6 changed files with 137 additions and 79 deletions
|
@ -38,7 +38,7 @@ class Dimens {
|
|||
// `CenteredSlider`
|
||||
static const double cameraSliderTrackHeight = grid4;
|
||||
static const double cameraSliderTrackRadius = cameraSliderTrackHeight / 2;
|
||||
static const double cameraSliderHandleSize = 32;
|
||||
static const double cameraSliderHandleSize = 24;
|
||||
static const double cameraSliderHandleIconSize = cameraSliderHandleSize * 2 / 3;
|
||||
|
||||
// Dialog
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:lightmeter/generated/l10n.dart';
|
||||
import 'package:lightmeter/res/dimens.dart';
|
||||
import 'package:lightmeter/screens/shared/centered_slider/widget_slider_centered.dart';
|
||||
import 'package:lightmeter/screens/shared/ruler_slider/widget_slider_ruler.dart';
|
||||
import 'package:lightmeter/utils/to_string_signed.dart';
|
||||
|
||||
class ExposureOffsetSlider extends StatelessWidget {
|
||||
|
@ -26,68 +25,15 @@ class ExposureOffsetSlider extends StatelessWidget {
|
|||
tooltip: S.of(context).tooltipResetToZero,
|
||||
),
|
||||
Expanded(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
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,
|
||||
min: range.start,
|
||||
max: range.end,
|
||||
onChanged: onChanged,
|
||||
),
|
||||
],
|
||||
child: RulerSlider(
|
||||
icon: Icons.light_mode,
|
||||
range: range,
|
||||
value: value,
|
||||
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(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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 {
|
||||
final RangeValues range;
|
||||
|
@ -15,12 +15,22 @@ class ZoomSlider extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return CenteredSlider(
|
||||
icon: const Icon(Icons.search),
|
||||
value: value,
|
||||
min: range.start,
|
||||
max: range.end,
|
||||
onChanged: onChanged,
|
||||
return Column(
|
||||
children: [
|
||||
const IconButton(
|
||||
icon: Icon(Icons.lock_open),
|
||||
onPressed: null,
|
||||
),
|
||||
Expanded(
|
||||
child: RulerSlider(
|
||||
icon: Icons.search,
|
||||
range: range,
|
||||
value: value,
|
||||
onChanged: onChanged,
|
||||
rulerValueAdapter: (value) => '${value.toStringAsFixed(0)}x',
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
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/zoom_slider/widget_slider_zoom.dart';
|
||||
|
@ -25,16 +24,14 @@ class CameraControls extends StatelessWidget {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: [
|
||||
Expanded(
|
||||
child: ExposureOffsetSlider(
|
||||
range: exposureOffsetRange,
|
||||
value: exposureOffsetValue,
|
||||
onChanged: onExposureOffsetChanged,
|
||||
),
|
||||
ExposureOffsetSlider(
|
||||
range: exposureOffsetRange,
|
||||
value: exposureOffsetValue,
|
||||
onChanged: onExposureOffsetChanged,
|
||||
),
|
||||
const SizedBox(height: Dimens.grid24),
|
||||
ZoomSlider(
|
||||
range: zoomRange,
|
||||
value: zoomValue,
|
||||
|
|
|
@ -157,7 +157,12 @@ class _CameraControlsBuilder extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: Dimens.paddingM),
|
||||
padding: const EdgeInsets.fromLTRB(
|
||||
Dimens.paddingL,
|
||||
Dimens.paddingM,
|
||||
0,
|
||||
Dimens.paddingL,
|
||||
),
|
||||
child: BlocBuilder<CameraContainerBloc, CameraContainerState>(
|
||||
builder: (context, state) {
|
||||
late final Widget child;
|
||||
|
|
100
lib/screens/shared/ruler_slider/widget_slider_ruler.dart
Normal file
100
lib/screens/shared/ruler_slider/widget_slider_ruler.dart
Normal 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(),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue