How to create a half screen custom camera view using Xamarin.Forms?


Isn't it fun,

to instantly listen to a blog on the go? PLAY !

 
 

half-screen-custom-camera

In this blog, we will be going to discuss how to create a half screen custom camera view using Xamarin.Forms. Xamarin is a cross-platform language of the .NET framework. This framework helps you in creating mobile applications. This mobile application is run on any platform like Android, IOS, Windows, and UWP (Universal Windows Platform). You have to create a design in Xamarin and then have to use XAML (Extensible Application Markup Language) page for creating the design.

How to create a half-screen custom camera view using Xamarin.Forms?

Please follow these steps to create a half-screen custom camera view using Xamarin.Forms.

Step 1: First you have created a new Xamarin project.

First select the cross-platform from the left side menu.

Then select Mobile-app (Xamarin.Forms).

Then select the destination to put the project in location.

After declare the unique name of your project and then click ok.

Figure 1: Create a new Xamarin Project.

Select the blank template.

Selecting your platform depending on your requirements.

And then press ok.

Figure 2: Select your template and Platform.

Step 2: After creating the project, create five folders are Model, View, ViewModel, Enum, and Custom renderer.

Step 3: After creating the folders, first you have to create the enum class in the enum folder and assign the name like CameraData.

File Name: CameraData.cs

Code:
namespace CustomCameraDemo
{
	public enum CameraData
	{
		Frontend,
		Backend
	}
}


Step 4: Now, create a class in the ViewModel folder and assign the name as ShowCamera.cs.

File Name: ShowCamera.cs

Code:
using System;
using System.Collections.Generic;
using Android.Content;
using Android.Hardware;
using Android.Runtime;
using Android.Views;

namespace CustomCameraDemo.Droid
{
	public sealed class ShowCamera : ViewGroup, ISurfaceHolderCallback
	{
		SurfaceView CameraView;
		ISurfaceHolder holder;
		Camera.Size previewSize;
		IList supportedPreviewSizes;
		Camera camera;
		IWindowManager windowManager;

		public bool IsPreviewing { get; set; }

		public Camera Preview {
			get { return camera; }
			set {
				camera = value;
				if (camera != null) {
					supportedPreviewSizes = Preview.GetParameters ().SupportedPreviewSizes;
					RequestLayout ();
				}
			}
		}

		public ShowCamera (Context context)
			: base (context)
		{
			CameraView= new SurfaceView (context);
			AddView (CameraView);

			windowManager = Context.GetSystemService (Context.WindowService).JavaCast ();

			IsPreviewing = false;
			holder = CameraView.Holder;
			holder.AddCallback (this);
		}

		protected override void OnMeasure (int widthMeasureSpec, int heightMeasureSpec)
		{
			int width = ResolveSize (SuggestedMinimumWidth, widthMeasureSpec);
			int height = ResolveSize (SuggestedMinimumHeight, heightMeasureSpec);
			SetMeasuredDimension (width, height);

			if (supportedPreviewSizes != null) {
				previewSize = GetOptimalPreviewSize (supportedPreviewSizes, width, height);
			}
		}

		protected override void OnPageLayout (bool changed, int l, int t, int r, int b)
		{
			var msw = MeasureSpec.MakeMeasureSpec (r - l, MeasureSpecMode.Exactly);
			var msh = MeasureSpec.MakeMeasureSpec (b - t, MeasureSpecMode.Exactly);

			CameraView.Measure (msw, msh);
			CameraView.Layout (0, 0, r - l, b - t);
		}

		public void SurfaceCreated (ISurfaceHolder holder)
		{
			try {
				if (Preview != null) {
					Preview.SetPreviewDisplay (holder);
				}
			} catch (Exception ex) {
				System.Diagnostics.Debug.WriteLine (@"ERROR: ", ex.Message);
			}
		}

		public void SurfaceDestroyed (ISurfaceHolder holder)
		{
			if (Preview != null) {
				Preview.StopPreview ();
			}
		}

		public void SurfaceChanged (ISurfaceHolder holder, Android.Graphics.Format format, int width, int height)
		{
			var parameters = Preview.GetParameters ();
			parameters.SetPreviewSize (previewSize.Width, previewSize.Height);
			RequestLayout ();

			switch (windowManager.DefaultDisplay.Rotation) {
			case SurfaceOrientation.Rotation0:
				camera.SetDisplayOrientation (90);
				break;
			case SurfaceOrientation.Rotation90:
				camera.SetDisplayOrientation (0);
				break;
			case SurfaceOrientation.Rotation270:
				camera.SetDisplayOrientation (180);
				break;
			}

			Preview.SetParameters (parameters);
			Preview.StartPreview ();
			IsPreviewing = true;
		}

		Camera.Size GetOptimalPreviewSize (IList sizes, int w, int h)
		{
			const double AspectTolerance = 0.1;
			double targetRatio = (double)w / h;

			if (sizes == null) {
				return null;
			}

			Camera.Size optimalSize = null;
			double minDiff = double.MaxValue;

			int targetHeight = h;
			foreach (Camera.Size size in sizes) {
				double ratio = (double)size.Width / size.Height;

				if (Math.Abs (ratio - targetRatio) > AspectTolerance)
					continue;
				if (Math.Abs (size.Height - targetHeight) < minDiff) {
					optimalSize = size;
					minDiff = Math.Abs (size.Height - targetHeight);
				}
			}

			if (optimalSize == null) {
				minDiff = double.MaxValue;
				foreach (Camera.Size size in sizes) {
					if (Math.Abs (size.Height - targetHeight) < minDiff) {
						optimalSize = size;
						minDiff = Math.Abs (size.Height - targetHeight);
					}
				}
			}
			return optimalSize;
		}
	}
}

Step 5: Create a Renderer class in the Custom Renderer folder and assign the name like CustomCameraPreviewRenderer.cs

File Name: CustomCameraPreviewRenderer.cs

Code:
using System;
using Android.Content;
using Android.Hardware;
using CustomRenderer.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(CustomRenderer.CameraPreview), typeof(CustomCameraPreviewRenderer))]
namespace CustomCameraDemo.Droid
{
    public class CustomCameraPreviewRenderer : ViewRenderer
    {
        ShowCamera cameraPreview;

        public CustomCameraPreviewRenderer(Context context) : base(context)
        {
        }

        protected override void OnElementChanged(ElementChangedEventArgs e)
        {
            base.OnElementChanged(e);

            if (e.OldElement != null)
            {
                
                cameraPreview.Click -= OnCameraPreviewClicked;
            }
            if (e.NewElement != null)
            {
                if (Control == null)
                {
                    cameraPreview = new ShowCamera(Context);
                    SetNativeControl(cameraPreview);
                }
                Control.Preview = Camera.Open((int)e.NewElement.Camera);

               
                cameraPreview.Click += OnCameraPreviewClicked;
            }
        }

        void OnCameraPreviewClicked(object sender, EventArgs e)
        {
            if (cameraPreview.IsPreviewing)
            {
                cameraPreview.Preview.StopPreview();
                cameraPreview.IsPreviewing = false;
            }
            else
            {
                cameraPreview.Preview.StartPreview();
                cameraPreview.IsPreviewing = true;
            }
        }

        protected override void Dispose (bool disposing)
        {
            if (disposing)
            {
                Control.Preview.Release();
            }
            base.Dispose(disposing);
        }
    }
}

One Stop Solution for Xamarin Mobile App Development

Your Search ends here.


Step 6: Create a new class for bindable property and assign the name like Showingcamera.cs.

File Name: Showingcamera.cs.

Code:
using Xamarin.Forms;

namespace CustomCameraDemo
{
	public class CameraPreview : View
	{
		public static readonly BindableProperty CameraScreenProperty = BindableProperty.Create (
			propertyName: "Camera",
			returnType: typeof(CameraData),
			declaringType: typeof(CameraPreview),
			defaultValue: CameraData.Backend);

		public CameraData Camera {
			get { return (CameraData)GetValue (CameraScreenProperty); }
			set { SetValue (CameraScreenProperty, value); }
		}
	}
}

Step 7: Create a design for showing the Camera. This file is added to the view folder and assigns a name like MainPage.xaml.

File Name: MainPage.xaml.

Code:


    
        
            
                
                
            

            
                
            

            

            

            
                
        
    

Step 8: Create the event method in the xaml class file.

File Name: MainPage.xaml.cs

Code:
using Rg.Plugins.Popup.Extensions;
using Xamarin.Forms;

namespace CustomCameraDemo
{
	public partial class MainPage : ContentPage
	{
		public MainPage ()
		{
			InitializeComponent ();
		}

        private async void Button_Clicked(object sender, System.EventArgs e)
        {
            await Navigation.PushPopupAsync(new MyPopupPage());
        }
    }
}

Conclusion

In this blog, we have explained how to create half screen custom camera view using Xamarin.Forms. We have also discussed about the Custom camera view with the explanation of its implementation.

How to create a half screen custom camera view using Xamarin.Forms?

half-screen-custom-camera

In this blog, we will be going to discuss how to create a half screen custom camera view using Xamarin.Forms. Xamarin is a cross-platform language of the .NET framework. This framework helps you in creating mobile applications. This mobile application is run on any platform like Android, IOS, Windows, and UWP (Universal Windows Platform). You have to create a design in Xamarin and then have to use XAML (Extensible Application Markup Language) page for creating the design.

How to create a half-screen custom camera view using Xamarin.Forms?

Please follow these steps to create a half-screen custom camera view using Xamarin.Forms.

Step 1: First you have created a new Xamarin project.

First select the cross-platform from the left side menu.

Then select Mobile-app (Xamarin.Forms).

Then select the destination to put the project in location.

After declare the unique name of your project and then click ok.

Figure 1: Create a new Xamarin Project.

Select the blank template.

Selecting your platform depending on your requirements.

And then press ok.

Figure 2: Select your template and Platform.

Step 2: After creating the project, create five folders are Model, View, ViewModel, Enum, and Custom renderer.

Step 3: After creating the folders, first you have to create the enum class in the enum folder and assign the name like CameraData.

File Name: CameraData.cs

Code:
namespace CustomCameraDemo
{
	public enum CameraData
	{
		Frontend,
		Backend
	}
}


Step 4: Now, create a class in the ViewModel folder and assign the name as ShowCamera.cs.

File Name: ShowCamera.cs

Code:
using System;
using System.Collections.Generic;
using Android.Content;
using Android.Hardware;
using Android.Runtime;
using Android.Views;

namespace CustomCameraDemo.Droid
{
	public sealed class ShowCamera : ViewGroup, ISurfaceHolderCallback
	{
		SurfaceView CameraView;
		ISurfaceHolder holder;
		Camera.Size previewSize;
		IList supportedPreviewSizes;
		Camera camera;
		IWindowManager windowManager;

		public bool IsPreviewing { get; set; }

		public Camera Preview {
			get { return camera; }
			set {
				camera = value;
				if (camera != null) {
					supportedPreviewSizes = Preview.GetParameters ().SupportedPreviewSizes;
					RequestLayout ();
				}
			}
		}

		public ShowCamera (Context context)
			: base (context)
		{
			CameraView= new SurfaceView (context);
			AddView (CameraView);

			windowManager = Context.GetSystemService (Context.WindowService).JavaCast ();

			IsPreviewing = false;
			holder = CameraView.Holder;
			holder.AddCallback (this);
		}

		protected override void OnMeasure (int widthMeasureSpec, int heightMeasureSpec)
		{
			int width = ResolveSize (SuggestedMinimumWidth, widthMeasureSpec);
			int height = ResolveSize (SuggestedMinimumHeight, heightMeasureSpec);
			SetMeasuredDimension (width, height);

			if (supportedPreviewSizes != null) {
				previewSize = GetOptimalPreviewSize (supportedPreviewSizes, width, height);
			}
		}

		protected override void OnPageLayout (bool changed, int l, int t, int r, int b)
		{
			var msw = MeasureSpec.MakeMeasureSpec (r - l, MeasureSpecMode.Exactly);
			var msh = MeasureSpec.MakeMeasureSpec (b - t, MeasureSpecMode.Exactly);

			CameraView.Measure (msw, msh);
			CameraView.Layout (0, 0, r - l, b - t);
		}

		public void SurfaceCreated (ISurfaceHolder holder)
		{
			try {
				if (Preview != null) {
					Preview.SetPreviewDisplay (holder);
				}
			} catch (Exception ex) {
				System.Diagnostics.Debug.WriteLine (@"ERROR: ", ex.Message);
			}
		}

		public void SurfaceDestroyed (ISurfaceHolder holder)
		{
			if (Preview != null) {
				Preview.StopPreview ();
			}
		}

		public void SurfaceChanged (ISurfaceHolder holder, Android.Graphics.Format format, int width, int height)
		{
			var parameters = Preview.GetParameters ();
			parameters.SetPreviewSize (previewSize.Width, previewSize.Height);
			RequestLayout ();

			switch (windowManager.DefaultDisplay.Rotation) {
			case SurfaceOrientation.Rotation0:
				camera.SetDisplayOrientation (90);
				break;
			case SurfaceOrientation.Rotation90:
				camera.SetDisplayOrientation (0);
				break;
			case SurfaceOrientation.Rotation270:
				camera.SetDisplayOrientation (180);
				break;
			}

			Preview.SetParameters (parameters);
			Preview.StartPreview ();
			IsPreviewing = true;
		}

		Camera.Size GetOptimalPreviewSize (IList sizes, int w, int h)
		{
			const double AspectTolerance = 0.1;
			double targetRatio = (double)w / h;

			if (sizes == null) {
				return null;
			}

			Camera.Size optimalSize = null;
			double minDiff = double.MaxValue;

			int targetHeight = h;
			foreach (Camera.Size size in sizes) {
				double ratio = (double)size.Width / size.Height;

				if (Math.Abs (ratio - targetRatio) > AspectTolerance)
					continue;
				if (Math.Abs (size.Height - targetHeight) < minDiff) {
					optimalSize = size;
					minDiff = Math.Abs (size.Height - targetHeight);
				}
			}

			if (optimalSize == null) {
				minDiff = double.MaxValue;
				foreach (Camera.Size size in sizes) {
					if (Math.Abs (size.Height - targetHeight) < minDiff) {
						optimalSize = size;
						minDiff = Math.Abs (size.Height - targetHeight);
					}
				}
			}
			return optimalSize;
		}
	}
}

Step 5: Create a Renderer class in the Custom Renderer folder and assign the name like CustomCameraPreviewRenderer.cs

File Name: CustomCameraPreviewRenderer.cs

Code:
using System;
using Android.Content;
using Android.Hardware;
using CustomRenderer.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(CustomRenderer.CameraPreview), typeof(CustomCameraPreviewRenderer))]
namespace CustomCameraDemo.Droid
{
    public class CustomCameraPreviewRenderer : ViewRenderer
    {
        ShowCamera cameraPreview;

        public CustomCameraPreviewRenderer(Context context) : base(context)
        {
        }

        protected override void OnElementChanged(ElementChangedEventArgs e)
        {
            base.OnElementChanged(e);

            if (e.OldElement != null)
            {
                
                cameraPreview.Click -= OnCameraPreviewClicked;
            }
            if (e.NewElement != null)
            {
                if (Control == null)
                {
                    cameraPreview = new ShowCamera(Context);
                    SetNativeControl(cameraPreview);
                }
                Control.Preview = Camera.Open((int)e.NewElement.Camera);

               
                cameraPreview.Click += OnCameraPreviewClicked;
            }
        }

        void OnCameraPreviewClicked(object sender, EventArgs e)
        {
            if (cameraPreview.IsPreviewing)
            {
                cameraPreview.Preview.StopPreview();
                cameraPreview.IsPreviewing = false;
            }
            else
            {
                cameraPreview.Preview.StartPreview();
                cameraPreview.IsPreviewing = true;
            }
        }

        protected override void Dispose (bool disposing)
        {
            if (disposing)
            {
                Control.Preview.Release();
            }
            base.Dispose(disposing);
        }
    }
}

One Stop Solution for Xamarin Mobile App Development

Your Search ends here.


Step 6: Create a new class for bindable property and assign the name like Showingcamera.cs.

File Name: Showingcamera.cs.

Code:
using Xamarin.Forms;

namespace CustomCameraDemo
{
	public class CameraPreview : View
	{
		public static readonly BindableProperty CameraScreenProperty = BindableProperty.Create (
			propertyName: "Camera",
			returnType: typeof(CameraData),
			declaringType: typeof(CameraPreview),
			defaultValue: CameraData.Backend);

		public CameraData Camera {
			get { return (CameraData)GetValue (CameraScreenProperty); }
			set { SetValue (CameraScreenProperty, value); }
		}
	}
}

Step 7: Create a design for showing the Camera. This file is added to the view folder and assigns a name like MainPage.xaml.

File Name: MainPage.xaml.

Code:


    
        
            
                
                
            

            
                
            

            

            

            
                
        
    

Step 8: Create the event method in the xaml class file.

File Name: MainPage.xaml.cs

Code:
using Rg.Plugins.Popup.Extensions;
using Xamarin.Forms;

namespace CustomCameraDemo
{
	public partial class MainPage : ContentPage
	{
		public MainPage ()
		{
			InitializeComponent ();
		}

        private async void Button_Clicked(object sender, System.EventArgs e)
        {
            await Navigation.PushPopupAsync(new MyPopupPage());
        }
    }
}

Conclusion

In this blog, we have explained how to create half screen custom camera view using Xamarin.Forms. We have also discussed about the Custom camera view with the explanation of its implementation.