Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Preview rotated when app isn't in natural orientation - Android API 21+ / CameraX #144

Open
Murilo-Perrone opened this issue Dec 21, 2020 · 4 comments

Comments

@Murilo-Perrone
Copy link

Whenever the view is rotated, preview image must rotate accordingly. Since that's not happening, we get a rotated preview window:
pic2

Experments in Fancycamera component with preview.setRotation(rotation: Int) were noneffective. This is actually a naive code problem, as mentioned in this stackoverflow topic. As explained in Husayn Hakeem's blog post, the recommended solution is to use PreviewView class from CameraX (see the implementation). Question is how to do that in a nativescript plugin?

NativeScript does not have a surface view, so the solution may to through programmatic binding of a child view. Possibly through NativeScript's PlaceHolder element, which allows the adding any native widget to the application.

@triniwiz
Copy link
Member

We can use the preview view by extending that instead of the textureview but they didn’t have a way to interact with the preview view using OpenGL which I would like to do soon to add support in the canvas plugin

@Murilo-Perrone
Copy link
Author

Murilo-Perrone commented Dec 22, 2020

Hmm now I see. Unfortunately PreviewView is final, so it can't be extended. And this guide indicates we can't mix our own surface or TextureView with a PreviewView.

So this would be a huge change:

  • from FancyCamera : FrameLayout holding CameraBase : TextureView
  • to PreviewView : FrameLayout

The PreviewView class applies a transformation matrix to the surface, and we can't copy that code because the methods are all internal and the code is too complex anyway. It would be easier if google made Preview.Builder.setTargetRotation or Preview.setTargetRotation to work readily with our TextureView. But that doesn't seem to be on their plans. So there is no middle ground.

For immediate results, I tried handling it all within camera-plus, based on View.setRotation. That seems doable, although it is a cheap workaround that would require a few adjustments to show up right. In the image below, I rotated FancyCamera and the buttons, but would still need to recalculate their locations (note they are in wrong position):

TestCam

Thoughts about this approach? My wonder is code maintenance.

@sublime392
Copy link

sublime392 commented Dec 23, 2020

Update: nvm, rotation seems to be working with Fancy Camera 3.0.0-alpha15.

@Murilo-Perrone can you give me a few more details about how you did your rotation? I need something that I can do right now, and what you have seems good enough. I don't need any details related to the buttons as I am already using my own. I just need to know how/where you set the rotation in camera-plus. Thanks!

@Murilo-Perrone
Copy link
Author

@sublime392 hi sorry for the delay. That tentative is based on rough view rotation, such as the CSS 'rotate' property:

public camLoaded(e: any): void {
  this.cam = e.object as CameraPlus;
  if (isAndroid) {
    this.cam.rotate = 90;

You can get same result through this.cam.nativeView.setRotation(90). This can respond to orientation changes detected by nativescript component:

constructor(private zone: NgZone) {
    on("orientationChanged",  (evt) => {
      setTimeout(() => this.onOrientationChanged(evt.eventName, evt.newValue), 1000)
    });
}
onOrientationChanged(eventName: string, newValue: string) {
    if (newValue == "landscape") {
        ...
    }
    if (newValue == "portrait") {
        ...
    }
}

In case you want to seek for a workaround within the plugin code, the above detection may be done with native code, as described in issue 143 . Then other adjustments can be tried in camera-plus.android.ts. Here is an example:

private _onLayoutChangeFn(...args: any[]) {
  console.log("_onLayoutChangeFn: ", args);
  const size = this.getActualSize();
  CLog('xml width/height:', size.width + 'x' + size.height);
  this.adjustRotation(); // <== NEW CODE
  this._initDefaultButtons();
}

private adjustRotation() {
  const viewAngle = this.nativeView.getDisplay().getRotation() * 90;
  CLog("viewAngle: " + viewAngle);
  // this.rotate = 360 - viewAngle;
  this._nativeView.setRotation(360 - viewAngle);
  const oldHeight = this._nativeView.height;
  this._nativeView.height = this._nativeView.width;
  this._nativeView.width = oldHeight;

  if (this._flashBtn) this._flashBtn.setRotation(viewAngle);
  if (this._takePicBtn) this._takePicBtn.setRotation(viewAngle);
  if (this._toggleCamBtn) this._toggleCamBtn.setRotation(viewAngle);
  if (this._galleryBtn) this._galleryBtn.setRotation(viewAngle);
  this._nativeView.requestLayout();
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants