Apparence-io / CamerAwesome

📸 Embedding a camera experience within your own app shouldn't be that hard. A flutter plugin to integrate awesome Android / iOS camera experience.
https://ApparenceKit.dev
MIT License
919 stars 207 forks source link

Screen orientation locked after navigating back from Camera view #241

Open CorjanM opened 1 year ago

CorjanM commented 1 year ago

Steps to Reproduce

Expected results

Actual results

Caused by following code in camera_awesome_builder.dart:

@override
void didChangeDependencies() {
  SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
  super.didChangeDependencies();
}

Fixed by calling SystemChrome.setPreferredOrientations(DeviceOrientation.values); on disposing the camera screen. Obviously the above fix can be improved but we allow all orientations so this is fine for us.

About your device

Brand Model OS
Apple iPhone 12 Pro Max 16.2

g-apparence commented 1 year ago

Hi, Yes we normally mentionned it in the documentation. If that was not clear, then we will make it more visible.

For a better user experience the camera widget locks the screen orientation and rotate icons only using the sensors. Without this the camera preview would be killed and recreated each time you rotate your screen (which is really annoying).

When you exit your camera page, you have to reinit your prefered orientations.

hope this help.

CorjanM commented 1 year ago

Thanks for the update!

KirioXX commented 1 year ago

Hi, I have a bit of a problem with reseting of the oritentation. I tried to reset the preference in WillPopScope but it seams like this is doing nothing. Is there any thing that I could have missed or could you please advice how to reset the orientation?

This is how I set it up:

import 'package:auto_route/auto_route.dart';
import 'package:camerawesome/camerawesome_plugin.dart';
import 'package:camerawesome/pigeon.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:path_provider/path_provider.dart';
import 'package:app/views/pages/utils/camera/camera_countdown.dart';
import 'package:app/views/pages/utils/camera/camera_layout.dart';
import 'package:uuid/uuid.dart';
import 'package:video_compress/video_compress.dart';

export 'package:camerawesome/camerawesome_plugin.dart' show CaptureMode;

class CameraPageResponse {
  CameraPageResponse({required this.filePath});
  final String filePath;
}

class CameraPage extends StatelessWidget {
  const CameraPage({
    super.key,
    this.captureMode = CaptureMode.photo,
    this.maxVideoDuration,
  });

  final CaptureMode captureMode;
  final Duration? maxVideoDuration;

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async {
        await SystemChrome.setPreferredOrientations(DeviceOrientation.values);
        return true;
      },
      child: Scaffold(
        body: CameraAwesomeBuilder.custom(
          saveConfig: captureMode == CaptureMode.photo
              ? SaveConfig.photo(
                  pathBuilder: () async {
                    final extDir = await getApplicationDocumentsDirectory();
                    return '${extDir.path}/${const Uuid().v4()}.jpg';
                  },
                )
              : SaveConfig.video(
                  pathBuilder: () async {
                    final extDir = await getApplicationDocumentsDirectory();
                    return '${extDir.path}/${const Uuid().v4()}.mp4';
                  },
                ),
          exifPreferences: ExifPreferences(
            saveGPSLocation: true,
          ),
          enableAudio: false,
          builder: (cameraState, previewSize, previewRect) {
            return cameraState.when(
              onPreparingCamera: (state) => const Center(
                child: CircularProgressIndicator(),
              ),
              onPhotoMode: (state) => _TakePhotoUI(state),
              onVideoMode: (state) => _RecordVideoUI(state),
              onVideoRecordingMode: (state) => _RecordVideoUI(
                state,
                maxVideoDuration: maxVideoDuration,
              ),
            );
          },
        ),
      ),
    );
  }
}

Thank you!

g-apparence commented 1 year ago

I will try your example and tell you.

KirioXX commented 1 year ago

Sorry @g-apparence what I have to forgot to say our devices are:

In case that helps.

g-apparence commented 1 year ago

Made this work. Actually this is not a camerAwesome bug.

You have to replace your pop call by : Navigator.maybePop(context);

Check the official documentation but here is how I understand it. As the result could be null we will call OnWillPop only if there is a parent route. if the route is null OnWillPop won't be called and can't be responsible to check if there is actually a parent.

Another solution is to call

await SystemChrome.setPreferredOrientations(DeviceOrientation.values);

In the parent route didChangeDependencies

KirioXX commented 1 year ago

Thanks for looking into this @g-apparence. I tried both of your suggestions without success.

For the will pop, it actually triggers the willPopScope but somehow the await SystemChrome.setPreferredOrientations(DeviceOrientation.values); is still not resetting the auto-rotating behaviour.

Your second suggestion to use didChangeDependencies on the parent is also not working because the dependencies on the parent screen are not changing and so the method is not triggered. I also tried to call the reset right after the response from the page is received with the same result.

My last try was to use the "dispose" method on the camera page with the same result as the will pop. It triggers the function but the reset is not working.

I'm a bit out of ideas. Could it be that camerAwesome is overwriting the reset when the camera instance is still active somehow?

g-apparence commented 1 year ago

That's weird. Maybe I didn't reprocuced your case completely. How do you route to the current page.

Either I'm thinking about a callback to restore device orientation. Maybe this could help. Something like

CameraAwesomeBuilder.awesome(
  onDispose: () {
    // reset your device orientation here
  }
);

Would that solve your problem?

KirioXX commented 1 year ago

Sorry for the delayed answer @g-apparence.

We use auto_route for routing with declarative navigation. What is special though about the page that opens the camera is that it is in a container transform. I'm not sure if that changes the context in a way that affects the rest.

The callback definitely would be helpful not just for this use case but also for cleanup actions that could happen after the camera closes. For the orientation reset, I would have expected that the package resets the orientation setting to the app defaults when it is disposed.

maciejbrzezinski commented 1 year ago

Hello, is there way to turn off the functionality of forcing portrait orientation? We've got situation when camera preview is just a part of the screen, and when user opens the page, the whole app is reoriented and it looks just weird. I've recorded the bahaviour:

https://user-images.githubusercontent.com/34410554/225605502-951502b4-ade3-41bd-a551-570353ab8bb2.mov

istornz commented 1 year ago

@maciejbrzezinski No currently it's not possible because Camerawesome do not support landscape mode at all... This is technically not possible at the moment (if we disable the portrait lock, camera rendering will be completely broken...)

apalala-dev commented 1 year ago

It seems that we may better respect apps orientation with this PR from Flutter: https://github.com/flutter/engine/pull/39763

Atm, there is no SystemChrome.getPreferredOrientations() so it's complicated to set back the app preferred orientations.

apalala-dev commented 1 year ago

Not good news but the mentioned Flutter PR has been closed (and not merged).

There's still an issue tracking this feature.

kevin4dhd commented 11 months ago

any solution?I don't want to force my screen to always be vertical

michielvi commented 9 months ago

@istornz Can there be at least an option in analysisOnly mode to disable this? Since there is no camera rendering in this mode, I don't think it is necessary to set it there to portrait?

Currently I am setting the orientation back to landscape after creating the analysisOnly mode and it is working perfectly for me. It's just annoying now that there is a switch to portrait and back to landscape, when you are already in landscape.

qwertyway commented 7 months ago

I would also like an option to disable this behavior