I'm trying to implement my own camera view like the Camera from "SnapChat". Coming from Xamarin.Forms I'm having a really hard time to understand the problem that I have. Is there any way to keep the full screen and remove the Stretch from the camera view.
Coming from Xamarin.Forms you can easily change the Aspect of the Image in the XAML, I couldn't find any similarly Property in Xamarin.Android. Is there some kind of Property?
Currently testing on Samsung S8+.
The camera view works like expected (Taking Pictures), but the View is Stretched image you can see here
this is my View code
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextureView
android:id="@+id/textureView"
android:layout_marginTop="-95dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<Button
android:id="@+id/toggleFlashButton"
android:layout_width="37dp"
android:layout_height="37dp"
android:layout_gravity="top|left"
android:layout_marginLeft="25dp"
android:layout_marginTop="25dp"
android:background="@drawable/NoFlashButton" />
<Button
android:id="@+id/switchCameraButton"
android:layout_width="35dp"
android:layout_height="26dp"
android:layout_gravity="top|right"
android:layout_marginRight="25dp"
android:layout_marginTop="25dp"
android:background="@drawable/ToggleCameraButton" />
<Button
android:id="@+id/takePhotoButton"
android:layout_width="65dp"
android:layout_height="65dp"
android:layout_marginBottom="15dp"
android:layout_gravity="center|bottom"
android:background="@drawable/TakePhotoButton" />
</FrameLayout>
and this is the code behind
public class CameraPage : PageRenderer, TextureView.ISurfaceTextureListener {
#region Fields
private Activity activity;
private Camera camera;
private CameraFacing cameraType;
private bool flashOn;
private byte[] imageBytes;
private SurfaceTexture surfaceTexture;
private Button switchCameraButton;
private Button takePhotoButton;
private TextureView textureView;
private Button toggleFlashButton;
private View view;
#endregion
#region Functions
public void OnSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
try {
camera = Camera.Open((int)cameraType);
textureView.LayoutParameters = new FrameLayout.LayoutParams(width, height, GravityFlags.FillVertical);
surfaceTexture = surface;
camera.SetPreviewTexture(surface);
PrepareAndStartCamera();
}
catch (Exception ex) {
System.Diagnostics.Debug.WriteLine(ex.Message);
System.Diagnostics.Debug.WriteLine(ex.StackTrace);
}
}
public bool OnSurfaceTextureDestroyed(SurfaceTexture surface) {
try {
camera.StopPreview();
camera.Release();
return true;
}
catch (Exception ex) {
System.Diagnostics.Debug.WriteLine(ex.Message);
System.Diagnostics.Debug.WriteLine(ex.StackTrace);
}
return true;
}
public void OnSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
PrepareAndStartCamera();
}
public void OnSurfaceTextureUpdated(SurfaceTexture surface) {
}
protected override void OnElementChanged(ElementChangedEventArgs<Page> e) {
base.OnElementChanged(e);
if (e.OldElement != null || Element == null)
return;
try {
activity = Context as Activity;
view = activity.LayoutInflater.Inflate(Resource.Layout.CameraLayout, this, false);
cameraType = CameraFacing.Back;
textureView = view.FindViewById<TextureView>(Resource.Id.textureView);
textureView.SurfaceTextureListener = this;
takePhotoButton = view.FindViewById<Button>(Resource.Id.takePhotoButton);
takePhotoButton.Click += TakePhotoButtonTapped;
switchCameraButton = view.FindViewById<Button>(Resource.Id.switchCameraButton);
switchCameraButton.Click += SwitchCameraButtonTapped;
toggleFlashButton = view.FindViewById<Button>(Resource.Id.toggleFlashButton);
toggleFlashButton.Click += ToggleFlashButtonTapped;
AddView(view);
}
catch (Exception ex) {
System.Diagnostics.Debug.WriteLine(ex.Message);
System.Diagnostics.Debug.WriteLine(ex.StackTrace);
}
}
protected override void OnLayout(bool changed, int l, int t, int r, int b) {
try {
base.OnLayout(changed, l, t, r, b);
var msw = MeasureSpec.MakeMeasureSpec(r - l, MeasureSpecMode.AtMost);
var msh = MeasureSpec.MakeMeasureSpec(b - t, MeasureSpecMode.AtMost);
view.Measure(msw, msh);
view.Layout(0, 0, r - l, b - t);
}
catch (Exception ex) {
System.Diagnostics.Debug.WriteLine(ex.Message);
System.Diagnostics.Debug.WriteLine(ex.StackTrace);
}
}
private void PrepareAndStartCamera() {
try {
camera.StopPreview();
var display = activity.WindowManager.DefaultDisplay;
if (display.Rotation == SurfaceOrientation.Rotation0) camera.SetDisplayOrientation(90);
if (display.Rotation == SurfaceOrientation.Rotation270) camera.SetDisplayOrientation(180);
camera.StartPreview();
}
catch (Exception ex) {
System.Diagnostics.Debug.WriteLine(ex.Message);
System.Diagnostics.Debug.WriteLine(ex.StackTrace);
}
}
private void SwitchCameraButtonTapped(object sender, EventArgs e) {
try {
if (cameraType == CameraFacing.Front) {
cameraType = CameraFacing.Back;
camera.StopPreview();
camera.Release();
camera = Camera.Open((int)cameraType);
camera.SetPreviewTexture(surfaceTexture);
PrepareAndStartCamera();
}
else {
cameraType = CameraFacing.Front;
camera.StopPreview();
camera.Release();
camera = Camera.Open((int)cameraType);
camera.SetPreviewTexture(surfaceTexture);
PrepareAndStartCamera();
}
}
catch (Exception ex) {
System.Diagnostics.Debug.WriteLine(ex.Message);
System.Diagnostics.Debug.WriteLine(ex.StackTrace);
}
}
private void ToggleFlashButtonTapped(object sender, EventArgs e) {
try {
flashOn = !flashOn;
if (flashOn) {
if (cameraType == CameraFacing.Back) {
toggleFlashButton.SetBackgroundResource(Resource.Drawable.FlashButton);
cameraType = CameraFacing.Back;
camera.StopPreview();
camera.Release();
camera = Camera.Open((int)cameraType);
var parameters = camera.GetParameters();
parameters.FlashMode = Camera.Parameters.FlashModeTorch;
camera.SetParameters(parameters);
camera.SetPreviewTexture(surfaceTexture);
PrepareAndStartCamera();
}
}
else {
toggleFlashButton.SetBackgroundResource(Resource.Drawable.NoFlashButton);
camera.StopPreview();
camera.Release();
camera = Camera.Open((int)cameraType);
var parameters = camera.GetParameters();
parameters.FlashMode = Camera.Parameters.FlashModeOff;
camera.SetParameters(parameters);
camera.SetPreviewTexture(surfaceTexture);
PrepareAndStartCamera();
}
}
catch (Exception ex) {
System.Diagnostics.Debug.WriteLine(ex.Message);
System.Diagnostics.Debug.WriteLine(ex.StackTrace);
}
}
private async void TakePhotoButtonTapped(object sender, EventArgs e) {
try {
camera.StopPreview();
DialogService.ShowLoading("Capturing...");
var image = textureView.Bitmap;
using (var imageStream = new MemoryStream()) {
await image.CompressAsync(Bitmap.CompressFormat.Png, 75, imageStream);
image.Recycle();
imageBytes = imageStream.ToArray();
}
camera.StartPreview();
await App.NavigationController.PushAsync(new ImagePreviewView(imageBytes));
DialogService.HideLoading();
}
catch (Exception ex) {
System.Diagnostics.Debug.WriteLine(ex.Message);
System.Diagnostics.Debug.WriteLine(ex.StackTrace);
}
}
#endregion
}