ML-209 Camera preview orientation is wrong (#210)

* lock orientation to `portraitUp`

* removed custom rotator for camera preview
This commit is contained in:
Vadim 2025-01-23 17:55:43 +01:00
parent 2439f7bfff
commit 8ecab836a3
3 changed files with 48 additions and 77 deletions

View file

@ -132,6 +132,7 @@ class CameraContainerBloc extends EvSourceBlocBase<CameraContainerEvent, CameraC
await _cameraController!.initialize();
await _cameraController!.setFlashMode(FlashMode.off);
await _cameraController!.lockCaptureOrientation(DeviceOrientation.portraitUp);
_zoomRange = await Future.wait<double>([
_cameraController!.getMinZoomLevel(),

View file

@ -1,50 +0,0 @@
import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class CameraView extends StatelessWidget {
final CameraController controller;
const CameraView({required this.controller, super.key});
@override
Widget build(BuildContext context) {
final value = controller.value;
return ValueListenableBuilder<CameraValue>(
valueListenable: controller,
builder: (_, __, Widget? child) => AspectRatio(
aspectRatio: _isLandscape(value) ? value.aspectRatio : (1 / value.aspectRatio),
child: Stack(
children: [
RotatedBox(
quarterTurns: _getQuarterTurns(value),
child: controller.buildPreview(),
),
child ?? const SizedBox(),
],
),
),
);
}
bool _isLandscape(CameraValue value) {
return <DeviceOrientation>[DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]
.contains(_getApplicableOrientation(value));
}
int _getQuarterTurns(CameraValue value) {
final Map<DeviceOrientation, int> turns = <DeviceOrientation, int>{
DeviceOrientation.portraitUp: 0,
DeviceOrientation.landscapeRight: 1,
DeviceOrientation.portraitDown: 2,
DeviceOrientation.landscapeLeft: 3,
};
return turns[_getApplicableOrientation(value)]!;
}
DeviceOrientation _getApplicableOrientation(CameraValue value) {
return value.isRecordingVideo
? value.recordingOrientation!
: (value.previewPauseOrientation ?? value.lockedCaptureOrientation ?? value.deviceOrientation);
}
}

View file

@ -1,18 +1,17 @@
import 'package:camera/camera.dart';
import 'package:camera/camera.dart' as camera;
import 'package:flutter/material.dart';
import 'package:lightmeter/data/models/camera_feature.dart';
import 'package:lightmeter/platform_config.dart';
import 'package:lightmeter/providers/user_preferences_provider.dart';
import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/metering/components/camera_container/components/camera_preview/components/camera_spot_detector/widget_camera_spot_detector.dart';
import 'package:lightmeter/screens/metering/components/camera_container/components/camera_preview/components/camera_view/widget_camera_view.dart';
import 'package:lightmeter/screens/metering/components/camera_container/components/camera_preview/components/camera_view_placeholder/widget_placeholder_camera_view.dart';
import 'package:lightmeter/screens/metering/components/camera_container/components/camera_preview/components/histogram/widget_histogram.dart';
import 'package:lightmeter/screens/metering/components/camera_container/models/camera_error_type.dart';
import 'package:lightmeter/utils/context_utils.dart';
class CameraPreview extends StatefulWidget {
final CameraController? controller;
final camera.CameraController? controller;
final CameraErrorType? error;
final ValueChanged<Offset?> onSpotTap;
@ -53,7 +52,7 @@ class _CameraPreviewState extends State<CameraPreview> {
}
class _CameraPreviewBuilder extends StatefulWidget {
final CameraController controller;
final camera.CameraController controller;
final ValueChanged<Offset?> onSpotTap;
const _CameraPreviewBuilder({
@ -97,29 +96,15 @@ class _CameraPreviewBuilderState extends State<_CameraPreviewBuilder> {
}
return ValueListenableBuilder<bool>(
valueListenable: _initializedNotifier,
builder: (context, value, child) => value
? Stack(
alignment: Alignment.bottomCenter,
children: [
CameraView(controller: widget.controller),
if (context.isPro) ...[
if (UserPreferencesProvider.cameraFeatureOf(
context,
CameraFeature.histogram,
))
Positioned(
left: Dimens.grid8,
right: Dimens.grid8,
bottom: Dimens.grid16,
child: CameraHistogram(controller: widget.controller),
),
if (UserPreferencesProvider.cameraFeatureOf(
context,
CameraFeature.spotMetering,
))
CameraSpotDetector(onSpotTap: widget.onSpotTap),
],
],
builder: (context, value, _) => value
? camera.CameraPreview(
widget.controller,
child: context.isPro
? _ProFeaturesOverlay(
controller: widget.controller,
onSpotTap: widget.onSpotTap,
)
: const SizedBox.shrink(),
)
: const SizedBox.shrink(),
);
@ -129,3 +114,38 @@ class _CameraPreviewBuilderState extends State<_CameraPreviewBuilder> {
_initializedNotifier.value = widget.controller.value.isInitialized;
}
}
class _ProFeaturesOverlay extends StatelessWidget {
final camera.CameraController controller;
final ValueChanged<Offset?> onSpotTap;
const _ProFeaturesOverlay({
required this.controller,
required this.onSpotTap,
});
@override
Widget build(BuildContext context) {
final bool hasHistogram = UserPreferencesProvider.cameraFeatureOf(
context,
CameraFeature.histogram,
);
final bool hasSpotMetering = UserPreferencesProvider.cameraFeatureOf(
context,
CameraFeature.histogram,
);
return Stack(
alignment: Alignment.bottomCenter,
children: [
if (hasHistogram)
Positioned(
left: Dimens.grid8,
right: Dimens.grid8,
bottom: Dimens.grid16,
child: CameraHistogram(controller: controller),
),
if (hasSpotMetering) CameraSpotDetector(onSpotTap: onSpotTap),
],
);
}
}