diff --git a/CustomRenderers/View/CustomRenderer/CameraPreview.cs b/CustomRenderers/View/CustomRenderer/CameraPreview.cs
old mode 100755
new mode 100644
index 467fb9c009..fd00144de4
--- a/CustomRenderers/View/CustomRenderer/CameraPreview.cs
+++ b/CustomRenderers/View/CustomRenderer/CameraPreview.cs
@@ -2,17 +2,18 @@
namespace CustomRenderer
{
- public class CameraPreview : View
- {
- public static readonly BindableProperty CameraProperty = BindableProperty.Create (
- propertyName: "Camera",
- returnType: typeof(CameraOptions),
- declaringType: typeof(CameraPreview),
- defaultValue: CameraOptions.Rear);
+ public class CameraPreview : View
+ {
+ public static readonly BindableProperty CameraProperty = BindableProperty.Create(
+ propertyName: "Camera",
+ returnType: typeof(CameraOptions),
+ declaringType: typeof(CameraPreview),
+ defaultValue: CameraOptions.Rear);
- public CameraOptions Camera {
- get { return (CameraOptions)GetValue (CameraProperty); }
- set { SetValue (CameraProperty, value); }
- }
- }
+ public CameraOptions Camera
+ {
+ get { return (CameraOptions)GetValue(CameraProperty); }
+ set { SetValue(CameraProperty, value); }
+ }
+ }
}
diff --git a/CustomRenderers/View/CustomRenderer/CustomRenderer.csproj b/CustomRenderers/View/CustomRenderer/CustomRenderer.csproj
index 38f0f50c80..1d9b11c45f 100644
--- a/CustomRenderers/View/CustomRenderer/CustomRenderer.csproj
+++ b/CustomRenderers/View/CustomRenderer/CustomRenderer.csproj
@@ -18,4 +18,4 @@
-
\ No newline at end of file
+
diff --git a/CustomRenderers/View/CustomRenderer/MainPage.xaml b/CustomRenderers/View/CustomRenderer/MainPage.xaml
old mode 100755
new mode 100644
index 63f5865c80..db83ac73ee
--- a/CustomRenderers/View/CustomRenderer/MainPage.xaml
+++ b/CustomRenderers/View/CustomRenderer/MainPage.xaml
@@ -3,12 +3,11 @@
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:CustomRenderer;assembly=CustomRenderer"
x:Class="CustomRenderer.MainPage"
- Padding="0,20,0,0"
Title="Main Page">
-
-
-
-
-
-
+
+
+
+
diff --git a/CustomRenderers/View/Droid/AutoFitTextureView.cs b/CustomRenderers/View/Droid/AutoFitTextureView.cs
new file mode 100644
index 0000000000..e41ae3f0c0
--- /dev/null
+++ b/CustomRenderers/View/Droid/AutoFitTextureView.cs
@@ -0,0 +1,84 @@
+using System;
+using Android.Content;
+using Android.Runtime;
+using Android.Util;
+using Android.Views;
+
+namespace CustomRenderer.Droid
+{
+ public class AutoFitTextureView : TextureView
+ {
+ int mRatioWidth = 0;
+ int mRatioHeight = 0;
+ readonly object locker = new object();
+
+ public AutoFitTextureView(Context context) : this(context, null)
+ {
+ }
+
+ public AutoFitTextureView(Context context, IAttributeSet attrs) : this(context, attrs, 0)
+ {
+ }
+
+ public AutoFitTextureView(Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
+ {
+ }
+
+ protected AutoFitTextureView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
+ {
+ }
+
+ public void SetAspectRatio(int width, int height)
+ {
+ if (width == 0 || height == 0)
+ {
+ throw new ArgumentException("Size can't be negative.");
+ }
+
+ mRatioWidth = width;
+ mRatioHeight = height;
+ RequestLayout();
+ }
+
+ protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
+ {
+ base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
+
+ int width = MeasureSpec.GetSize(widthMeasureSpec);
+ int height = MeasureSpec.GetSize(heightMeasureSpec);
+
+ if (mRatioWidth == 0 || mRatioHeight == 0)
+ {
+ SetMeasuredDimension(width, height);
+ }
+ else
+ {
+ if (width < (float)height * mRatioWidth / mRatioHeight)
+ {
+ SetMeasuredDimension(width, width * mRatioHeight / mRatioWidth);
+ }
+ else
+ {
+ SetMeasuredDimension(height * mRatioWidth / mRatioHeight, height);
+ }
+ }
+ }
+
+ public void ClearCanvas(Android.Graphics.Color color)
+ {
+ using var canvas = LockCanvas(null);
+ lock (locker)
+ {
+ try
+ {
+ canvas.DrawColor(color);
+ }
+ finally
+ {
+ UnlockCanvasAndPost(canvas);
+ }
+ Invalidate();
+ }
+ }
+ }
+}
diff --git a/CustomRenderers/View/Droid/CameraCaptureStateListener.cs b/CustomRenderers/View/Droid/CameraCaptureStateListener.cs
new file mode 100644
index 0000000000..5cfab93105
--- /dev/null
+++ b/CustomRenderers/View/Droid/CameraCaptureStateListener.cs
@@ -0,0 +1,14 @@
+using System;
+using Android.Hardware.Camera2;
+
+namespace CustomRenderer.Droid
+{
+ class CameraCaptureStateListener : CameraCaptureSession.StateCallback
+ {
+ public Action OnConfigureFailedAction;
+ public Action OnConfiguredAction;
+
+ public override void OnConfigureFailed(CameraCaptureSession session) => OnConfigureFailedAction?.Invoke(session);
+ public override void OnConfigured(CameraCaptureSession session) => OnConfiguredAction?.Invoke(session);
+ }
+}
diff --git a/CustomRenderers/View/Droid/CameraFragment.cs b/CustomRenderers/View/Droid/CameraFragment.cs
new file mode 100644
index 0000000000..15817068af
--- /dev/null
+++ b/CustomRenderers/View/Droid/CameraFragment.cs
@@ -0,0 +1,552 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Android;
+using Android.Content;
+using Android.Content.PM;
+using Android.Graphics;
+using Android.Hardware.Camera2;
+using Android.Hardware.Camera2.Params;
+using Android.OS;
+using Android.Runtime;
+using Android.Views;
+//using AndroidX.Core.Content;
+//using AndroidX.Fragment.App;
+using Android.Support.V4.Content;
+using Android.Support.V4.App;
+using Java.Lang;
+using Java.Util.Concurrent;
+using Xamarin.Forms.Platform.Android;
+
+namespace CustomRenderer.Droid
+{
+ class CameraFragment : Fragment, TextureView.ISurfaceTextureListener
+ {
+ CameraDevice device;
+ CaptureRequest.Builder sessionBuilder;
+ CameraCaptureSession session;
+ CameraTemplate cameraTemplate;
+ CameraManager manager;
+
+ bool cameraPermissionsGranted;
+ bool busy;
+ bool repeatingIsRunning;
+ int sensorOrientation;
+ string cameraId;
+ LensFacing cameraType;
+
+ Android.Util.Size previewSize;
+
+ HandlerThread backgroundThread;
+ Handler backgroundHandler = null;
+
+ Java.Util.Concurrent.Semaphore captureSessionOpenCloseLock = new Java.Util.Concurrent.Semaphore(1);
+
+ AutoFitTextureView texture;
+
+ TaskCompletionSource initTaskSource;
+ TaskCompletionSource permissionsRequested;
+
+ CameraManager Manager => manager ??= (CameraManager)Context.GetSystemService(Context.CameraService);
+
+ bool IsBusy
+ {
+ get => device == null || busy;
+ set
+ {
+ busy = value;
+ }
+ }
+
+ bool Available;
+
+ public CameraPreview Element { get; set; }
+
+ #region Constructors
+
+ public CameraFragment()
+ {
+ }
+
+ public CameraFragment(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
+ {
+ }
+
+ #endregion
+
+ #region Overrides
+
+ public override Android.Views.View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) => inflater.Inflate(Resource.Layout.CameraFragment, null);
+ public override void OnViewCreated(Android.Views.View view, Bundle savedInstanceState) => texture = view.FindViewById(Resource.Id.cameratexture);
+
+ public override void OnPause()
+ {
+ CloseSession();
+ StopBackgroundThread();
+ base.OnPause();
+ }
+
+ public override async void OnResume()
+ {
+ base.OnResume();
+
+ StartBackgroundThread();
+ if (texture is null)
+ {
+ return;
+ }
+ if (texture.IsAvailable)
+ {
+ View?.SetBackgroundColor(Element.BackgroundColor.ToAndroid());
+ cameraTemplate = CameraTemplate.Preview;
+ await RetrieveCameraDevice(force: true);
+ }
+ else
+ {
+ texture.SurfaceTextureListener = this;
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ CloseDevice();
+ base.Dispose(disposing);
+ }
+
+ #endregion
+
+ #region Public methods
+
+ public async Task RetrieveCameraDevice(bool force = false)
+ {
+ if (Context == null || (!force && initTaskSource != null))
+ {
+ return;
+ }
+
+ if (device != null)
+ {
+ CloseDevice();
+ }
+
+ await RequestCameraPermissions();
+ if (!cameraPermissionsGranted)
+ {
+ return;
+ }
+
+ if (!captureSessionOpenCloseLock.TryAcquire(2500, TimeUnit.Milliseconds))
+ {
+ throw new RuntimeException("Timeout waiting to lock camera opening.");
+ }
+
+ IsBusy = true;
+ cameraId = GetCameraId();
+
+ if (string.IsNullOrEmpty(cameraId))
+ {
+ IsBusy = false;
+ captureSessionOpenCloseLock.Release();
+ Console.WriteLine("No camera found");
+ }
+ else
+ {
+ try
+ {
+ CameraCharacteristics characteristics = Manager.GetCameraCharacteristics(cameraId);
+ StreamConfigurationMap map = (StreamConfigurationMap)characteristics.Get(CameraCharacteristics.ScalerStreamConfigurationMap);
+
+ previewSize = ChooseOptimalSize(map.GetOutputSizes(Class.FromType(typeof(SurfaceTexture))),
+ texture.Width, texture.Height, GetMaxSize(map.GetOutputSizes((int)ImageFormatType.Jpeg)));
+ sensorOrientation = (int)characteristics.Get(CameraCharacteristics.SensorOrientation);
+ cameraType = (LensFacing)(int)characteristics.Get(CameraCharacteristics.LensFacing);
+
+ if (Resources.Configuration.Orientation == Android.Content.Res.Orientation.Landscape)
+ {
+ texture.SetAspectRatio(previewSize.Width, previewSize.Height);
+ }
+ else
+ {
+ texture.SetAspectRatio(previewSize.Height, previewSize.Width);
+ }
+
+ initTaskSource = new TaskCompletionSource();
+ Manager.OpenCamera(cameraId, new CameraStateListener
+ {
+ OnOpenedAction = device => initTaskSource?.TrySetResult(device),
+ OnDisconnectedAction = device =>
+ {
+ initTaskSource?.TrySetResult(null);
+ CloseDevice(device);
+ },
+ OnErrorAction = (device, error) =>
+ {
+ initTaskSource?.TrySetResult(device);
+ Console.WriteLine($"Camera device error: {error}");
+ CloseDevice(device);
+ },
+ OnClosedAction = device =>
+ {
+ initTaskSource?.TrySetResult(null);
+ CloseDevice(device);
+ }
+ }, backgroundHandler);
+
+ captureSessionOpenCloseLock.Release();
+ device = await initTaskSource.Task;
+ initTaskSource = null;
+ if (device != null)
+ {
+ await PrepareSession();
+ }
+ }
+ catch (Java.Lang.Exception ex)
+ {
+ Console.WriteLine("Failed to open camera.", ex);
+ Available = false;
+ }
+ finally
+ {
+ IsBusy = false;
+ }
+ }
+ }
+
+ public void UpdateRepeatingRequest()
+ {
+ if (session == null || sessionBuilder == null)
+ {
+ return;
+ }
+
+ IsBusy = true;
+ try
+ {
+ if (repeatingIsRunning)
+ {
+ session.StopRepeating();
+ }
+
+ sessionBuilder.Set(CaptureRequest.ControlMode, (int)ControlMode.Auto);
+ sessionBuilder.Set(CaptureRequest.ControlAeMode, (int)ControlAEMode.On);
+ session.SetRepeatingRequest(sessionBuilder.Build(), listener: null, backgroundHandler);
+ repeatingIsRunning = true;
+ }
+ catch (Java.Lang.Exception error)
+ {
+ Console.WriteLine("Update preview exception.", error);
+ }
+ finally
+ {
+ IsBusy = false;
+ }
+ }
+
+ #endregion
+
+ void StartBackgroundThread()
+ {
+ backgroundThread = new HandlerThread("CameraBackground");
+ backgroundThread.Start();
+ backgroundHandler = new Handler(backgroundThread.Looper);
+ }
+
+ void StopBackgroundThread()
+ {
+ if (backgroundThread == null)
+ {
+ return;
+ }
+
+ backgroundThread.QuitSafely();
+ try
+ {
+ backgroundThread.Join();
+ backgroundThread = null;
+ backgroundHandler = null;
+ }
+ catch (InterruptedException ex)
+ {
+ Console.WriteLine("Error stopping background thread.", ex);
+ }
+ }
+
+ Android.Util.Size GetMaxSize(Android.Util.Size[] imageSizes)
+ {
+ Android.Util.Size maxSize = null;
+ long maxPixels = 0;
+ for (int i = 0; i < imageSizes.Length; i++)
+ {
+ long currentPixels = imageSizes[i].Width * imageSizes[i].Height;
+ if (currentPixels > maxPixels)
+ {
+ maxSize = imageSizes[i];
+ maxPixels = currentPixels;
+ }
+ }
+ return maxSize;
+ }
+
+ Android.Util.Size ChooseOptimalSize(Android.Util.Size[] choices, int width, int height, Android.Util.Size aspectRatio)
+ {
+ List bigEnough = new List();
+ int w = aspectRatio.Width;
+ int h = aspectRatio.Height;
+
+ foreach (Android.Util.Size option in choices)
+ {
+ if (option.Height == option.Width * h / w && option.Width >= width && option.Height >= height)
+ {
+ bigEnough.Add(option);
+ }
+ }
+
+ if (bigEnough.Count > 0)
+ {
+ int minArea = bigEnough.Min(s => s.Width * s.Height);
+ return bigEnough.First(s => s.Width * s.Height == minArea);
+ }
+ else
+ {
+ Console.WriteLine("Couldn't find any suitable preview size.");
+ return choices[0];
+ }
+ }
+
+ string GetCameraId()
+ {
+ string[] cameraIdList = Manager.GetCameraIdList();
+ if (cameraIdList.Length == 0)
+ {
+ return null;
+ }
+
+ string FilterCameraByLens(LensFacing lensFacing)
+ {
+ foreach (string id in cameraIdList)
+ {
+ CameraCharacteristics characteristics = Manager.GetCameraCharacteristics(id);
+ if (lensFacing == (LensFacing)(int)characteristics.Get(CameraCharacteristics.LensFacing))
+ {
+ return id;
+ }
+ }
+ return null;
+ }
+
+ return (Element.Camera == CameraOptions.Front) ? FilterCameraByLens(LensFacing.Front) : FilterCameraByLens(LensFacing.Back);
+ }
+
+ async Task PrepareSession()
+ {
+ IsBusy = true;
+ try
+ {
+ CloseSession();
+ sessionBuilder = device.CreateCaptureRequest(cameraTemplate);
+
+ List surfaces = new List();
+ if (texture.IsAvailable && previewSize != null)
+ {
+ var texture = this.texture.SurfaceTexture;
+ texture.SetDefaultBufferSize(previewSize.Width, previewSize.Height);
+ Surface previewSurface = new Surface(texture);
+ surfaces.Add(previewSurface);
+ sessionBuilder.AddTarget(previewSurface);
+ }
+
+ TaskCompletionSource tcs = new TaskCompletionSource();
+ device.CreateCaptureSession(surfaces, new CameraCaptureStateListener
+ {
+ OnConfigureFailedAction = captureSession =>
+ {
+ tcs.SetResult(null);
+ Console.WriteLine("Failed to create capture session.");
+ },
+ OnConfiguredAction = captureSession => tcs.SetResult(captureSession)
+ }, null);
+
+ session = await tcs.Task;
+ if (session != null)
+ {
+ UpdateRepeatingRequest();
+ }
+ }
+ catch (Java.Lang.Exception ex)
+ {
+ Available = false;
+ Console.WriteLine("Capture error.", ex);
+ }
+ finally
+ {
+ Available = session != null;
+ IsBusy = false;
+ }
+ }
+
+ void CloseSession()
+ {
+ repeatingIsRunning = false;
+ if (session == null)
+ {
+ return;
+ }
+
+ try
+ {
+ session.StopRepeating();
+ session.AbortCaptures();
+ session.Close();
+ session.Dispose();
+ session = null;
+ }
+ catch (CameraAccessException ex)
+ {
+ Console.WriteLine("Camera access error.", ex);
+ }
+ catch (Java.Lang.Exception ex)
+ {
+ Console.WriteLine("Error closing device.", ex);
+ }
+ }
+
+ void CloseDevice(CameraDevice inputDevice)
+ {
+ if (inputDevice == device)
+ {
+ CloseDevice();
+ }
+ }
+
+ void CloseDevice()
+ {
+ CloseSession();
+
+ try
+ {
+ if (sessionBuilder != null)
+ {
+ sessionBuilder.Dispose();
+ sessionBuilder = null;
+ }
+ if (device != null)
+ {
+ device.Close();
+ device = null;
+ }
+ }
+ catch (Java.Lang.Exception error)
+ {
+ Console.WriteLine("Error closing device.", error);
+ }
+ }
+
+ void ConfigureTransform(int viewWidth, int viewHeight)
+ {
+ if (texture == null || previewSize == null || previewSize.Width == 0 || previewSize.Height == 0)
+ {
+ return;
+ }
+
+ var matrix = new Matrix();
+ var viewRect = new RectF(0, 0, viewWidth, viewHeight);
+ var bufferRect = new RectF(0, 0, previewSize.Height, previewSize.Width);
+ var centerX = viewRect.CenterX();
+ var centerY = viewRect.CenterY();
+ bufferRect.Offset(centerX - bufferRect.CenterX(), centerY - bufferRect.CenterY());
+ matrix.SetRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.Fill);
+ matrix.PostRotate(GetCaptureOrientation(), centerX, centerY);
+ texture.SetTransform(matrix);
+ }
+
+ int GetCaptureOrientation()
+ {
+ int frontOffset = cameraType == LensFacing.Front ? 90 : -90;
+ return (360 + sensorOrientation - GetDisplayRotationDegrees() + frontOffset) % 360;
+ }
+
+ int GetDisplayRotationDegrees() =>
+ GetDisplayRotation() switch
+ {
+ SurfaceOrientation.Rotation90 => 90,
+ SurfaceOrientation.Rotation180 => 180,
+ SurfaceOrientation.Rotation270 => 270,
+ _ => 0
+ };
+
+ SurfaceOrientation GetDisplayRotation() => Android.App.Application.Context.GetSystemService(Context.WindowService).JavaCast().DefaultDisplay.Rotation;
+
+ #region Permissions
+
+ async Task RequestCameraPermissions()
+ {
+ if (permissionsRequested != null)
+ {
+ await permissionsRequested.Task;
+ }
+
+ List permissionsToRequest = new List();
+ cameraPermissionsGranted = ContextCompat.CheckSelfPermission(Context, Manifest.Permission.Camera) == Permission.Granted;
+ if (!cameraPermissionsGranted)
+ {
+ permissionsToRequest.Add(Manifest.Permission.Camera);
+ }
+
+ if (permissionsToRequest.Count > 0)
+ {
+ permissionsRequested = new TaskCompletionSource();
+ RequestPermissions(permissionsToRequest.ToArray(), requestCode: 1);
+ await permissionsRequested.Task;
+ permissionsRequested = null;
+ }
+ }
+
+ public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Permission[] grantResults)
+ {
+ if (requestCode != 1)
+ {
+ base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
+ return;
+ }
+
+ for (int i=0; i < permissions.Length; i++)
+ {
+ if (permissions[i] == Manifest.Permission.Camera)
+ {
+ cameraPermissionsGranted = grantResults[i] == Permission.Granted;
+ if (!cameraPermissionsGranted)
+ {
+ Console.WriteLine("No permission to use the camera.");
+ }
+ }
+ }
+ permissionsRequested?.TrySetResult(true);
+ }
+
+ #endregion
+
+ #region TextureView.ISurfaceTextureListener
+
+ async void TextureView.ISurfaceTextureListener.OnSurfaceTextureAvailable(SurfaceTexture surface, int width, int height)
+ {
+ View?.SetBackgroundColor(Element.BackgroundColor.ToAndroid());
+ cameraTemplate = CameraTemplate.Preview;
+ await RetrieveCameraDevice();
+ }
+
+ bool TextureView.ISurfaceTextureListener.OnSurfaceTextureDestroyed(SurfaceTexture surface)
+ {
+ CloseDevice();
+ return true;
+ }
+
+ void TextureView.ISurfaceTextureListener.OnSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) => ConfigureTransform(width, height);
+
+ void TextureView.ISurfaceTextureListener.OnSurfaceTextureUpdated(SurfaceTexture surface)
+ {
+ }
+
+ #endregion
+ }
+}
diff --git a/CustomRenderers/View/Droid/CameraPreview.cs b/CustomRenderers/View/Droid/CameraPreview.cs
deleted file mode 100755
index 70f688d22d..0000000000
--- a/CustomRenderers/View/Droid/CameraPreview.cs
+++ /dev/null
@@ -1,143 +0,0 @@
-using System;
-using System.Collections.Generic;
-using Android.Content;
-using Android.Hardware;
-using Android.Runtime;
-using Android.Views;
-
-namespace CustomRenderer.Droid
-{
- public sealed class CameraPreview : ViewGroup, ISurfaceHolderCallback
- {
- SurfaceView surfaceView;
- 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 CameraPreview (Context context)
- : base (context)
- {
- surfaceView = new SurfaceView (context);
- AddView (surfaceView);
-
- windowManager = Context.GetSystemService (Context.WindowService).JavaCast ();
-
- IsPreviewing = false;
- holder = surfaceView.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 OnLayout (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);
-
- surfaceView.Measure (msw, msh);
- surfaceView.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;
- }
- }
-}
diff --git a/CustomRenderers/View/Droid/CameraPreviewRenderer.cs b/CustomRenderers/View/Droid/CameraPreviewRenderer.cs
index 37b8e5b994..0088ce2f06 100644
--- a/CustomRenderers/View/Droid/CameraPreviewRenderer.cs
+++ b/CustomRenderers/View/Droid/CameraPreviewRenderer.cs
@@ -1,65 +1,215 @@
using System;
+using System.ComponentModel;
+//using AndroidX.Fragment.App;
+using Android.Support.V4.App;
using Android.Content;
-using Android.Hardware;
+using Android.Views;
+using Android.Widget;
using CustomRenderer.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
+using Xamarin.Forms.Platform.Android.FastRenderers;
[assembly: ExportRenderer(typeof(CustomRenderer.CameraPreview), typeof(CameraPreviewRenderer))]
namespace CustomRenderer.Droid
{
- public class CameraPreviewRenderer : ViewRenderer
+ public class CameraPreviewRenderer : FrameLayout, IVisualElementRenderer, IViewRenderer
{
- CameraPreview cameraPreview;
+ int? defaultLabelFor;
+ bool disposed;
+ CameraPreview element;
+ VisualElementTracker visualElementTracker;
+ VisualElementRenderer visualElementRenderer;
+ FragmentManager fragmentManager;
+ CameraFragment cameraFragment;
+
+ FragmentManager FragmentManager => fragmentManager ??= Context.GetFragmentManager();
+
+ public event EventHandler ElementChanged;
+ public event EventHandler ElementPropertyChanged;
+
+ CameraPreview Element
+ {
+ get => element;
+ set
+ {
+ if (element == value)
+ {
+ return;
+ }
+
+ var oldElement = element;
+ element = value;
+ OnElementChanged(new ElementChangedEventArgs(oldElement, element));
+ }
+ }
public CameraPreviewRenderer(Context context) : base(context)
{
+ visualElementRenderer = new VisualElementRenderer(this);
}
- protected override void OnElementChanged(ElementChangedEventArgs e)
+ void OnElementChanged(ElementChangedEventArgs e)
{
- base.OnElementChanged(e);
+ CameraFragment newFragment = null;
if (e.OldElement != null)
{
- // Unsubscribe
- cameraPreview.Click -= OnCameraPreviewClicked;
+ e.OldElement.PropertyChanged -= OnElementPropertyChanged;
+ cameraFragment.Dispose();
}
if (e.NewElement != null)
{
- if (Control == null)
+ this.EnsureId();
+
+ e.NewElement.PropertyChanged += OnElementPropertyChanged;
+
+ ElevationHelper.SetElevation(this, e.NewElement);
+ newFragment = new CameraFragment { Element = element };
+ }
+
+ FragmentManager.BeginTransaction()
+ .Replace(Id, cameraFragment = newFragment, "camera")
+ .Commit();
+ ElementChanged?.Invoke(this, new VisualElementChangedEventArgs(e.OldElement, e.NewElement));
+ }
+
+ async void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ ElementPropertyChanged?.Invoke(this, e);
+
+ switch (e.PropertyName)
+ {
+ case "Width":
+ await cameraFragment.RetrieveCameraDevice();
+ break;
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposed)
+ {
+ return;
+ }
+
+ cameraFragment.Dispose();
+ disposed = true;
+
+ if (disposing)
+ {
+ SetOnClickListener(null);
+ SetOnTouchListener(null);
+
+ if (visualElementTracker != null)
{
- cameraPreview = new CameraPreview(Context);
- SetNativeControl(cameraPreview);
+ visualElementTracker.Dispose();
+ visualElementTracker = null;
}
- Control.Preview = Camera.Open((int)e.NewElement.Camera);
- // Subscribe
- cameraPreview.Click += OnCameraPreviewClicked;
+ if (visualElementRenderer != null)
+ {
+ visualElementRenderer.Dispose();
+ visualElementRenderer = null;
+ }
+
+ if (Element != null)
+ {
+ Element.PropertyChanged -= OnElementPropertyChanged;
+
+ if (Platform.GetRenderer(Element) == this)
+ {
+ Platform.SetRenderer(Element, null);
+ }
+ }
}
+
+ base.Dispose(disposing);
}
- void OnCameraPreviewClicked(object sender, EventArgs e)
+ #region IViewRenderer
+
+ void IViewRenderer.MeasureExactly() => MeasureExactly(this, Element, Context);
+
+ static void MeasureExactly(Android.Views.View control, VisualElement element, Context context)
{
- if (cameraPreview.IsPreviewing)
+ if (control == null || element == null)
{
- cameraPreview.Preview.StopPreview();
- cameraPreview.IsPreviewing = false;
+ return;
}
- else
+
+ double width = element.Width;
+ double height = element.Height;
+
+ if (width <= 0 || height <= 0)
{
- cameraPreview.Preview.StartPreview();
- cameraPreview.IsPreviewing = true;
+ return;
}
+
+ int realWidth = (int)context.ToPixels(width);
+ int realHeight = (int)context.ToPixels(height);
+
+ int widthMeasureSpec = MeasureSpecFactory.MakeMeasureSpec(realWidth, MeasureSpecMode.Exactly);
+ int heightMeasureSpec = MeasureSpecFactory.MakeMeasureSpec(realHeight, MeasureSpecMode.Exactly);
+
+ control.Measure(widthMeasureSpec, heightMeasureSpec);
}
- protected override void Dispose(bool disposing)
+ #endregion
+
+ #region IVisualElementRenderer
+
+ VisualElement IVisualElementRenderer.Element => Element;
+
+ VisualElementTracker IVisualElementRenderer.Tracker => visualElementTracker;
+
+ ViewGroup IVisualElementRenderer.ViewGroup => null;
+
+ Android.Views.View IVisualElementRenderer.View => this;
+
+ SizeRequest IVisualElementRenderer.GetDesiredSize(int widthConstraint, int heightConstraint)
{
- if (disposing)
+ Measure(widthConstraint, heightConstraint);
+ SizeRequest result = new SizeRequest(new Size(MeasuredWidth, MeasuredHeight), new Size(Context.ToPixels(20), Context.ToPixels(20)));
+ return result;
+ }
+
+ void IVisualElementRenderer.SetElement(VisualElement element)
+ {
+ if (!(element is CameraPreview camera))
{
- Control.Preview.Release();
+ throw new ArgumentException($"{nameof(element)} must be of type {nameof(CameraPreview)}");
}
- base.Dispose(disposing);
+
+ if (visualElementTracker == null)
+ {
+ visualElementTracker = new VisualElementTracker(this);
+ }
+ Element = camera;
+ }
+
+ void IVisualElementRenderer.SetLabelFor(int? id)
+ {
+ if (defaultLabelFor == null)
+ {
+ defaultLabelFor = LabelFor;
+ }
+ LabelFor = (int)(id ?? defaultLabelFor);
+ }
+
+ void IVisualElementRenderer.UpdateLayout() => visualElementTracker?.UpdateLayout();
+
+ #endregion
+
+ static class MeasureSpecFactory
+ {
+ public static int GetSize(int measureSpec)
+ {
+ const int modeMask = 0x3 << 30;
+ return measureSpec & ~modeMask;
+ }
+
+ public static int MakeMeasureSpec(int size, MeasureSpecMode mode) => size + (int)mode;
}
}
}
diff --git a/CustomRenderers/View/Droid/CameraStateListener.cs b/CustomRenderers/View/Droid/CameraStateListener.cs
new file mode 100644
index 0000000000..4e01cdd91d
--- /dev/null
+++ b/CustomRenderers/View/Droid/CameraStateListener.cs
@@ -0,0 +1,18 @@
+using System;
+using Android.Hardware.Camera2;
+
+namespace CustomRenderer.Droid
+{
+ public class CameraStateListener : CameraDevice.StateCallback
+ {
+ public Action OnOpenedAction;
+ public Action OnDisconnectedAction;
+ public Action OnErrorAction;
+ public Action OnClosedAction;
+
+ public override void OnOpened(CameraDevice camera) => OnOpenedAction?.Invoke(camera);
+ public override void OnDisconnected(CameraDevice camera) => OnDisconnectedAction?.Invoke(camera);
+ public override void OnError(CameraDevice camera, CameraError error) => OnErrorAction(camera, error);
+ public override void OnClosed(CameraDevice camera) => OnClosedAction(camera);
+ }
+}
diff --git a/CustomRenderers/View/Droid/CustomRenderer.Droid.csproj b/CustomRenderers/View/Droid/CustomRenderer.Droid.csproj
index b976a42686..6047328cd9 100644
--- a/CustomRenderers/View/Droid/CustomRenderer.Droid.csproj
+++ b/CustomRenderers/View/Droid/CustomRenderer.Droid.csproj
@@ -58,7 +58,10 @@
-
+
+
+
+
@@ -74,12 +77,14 @@
+
+
+
+
-
-
-
\ No newline at end of file
+
diff --git a/CustomRenderers/View/Droid/MainActivity.cs b/CustomRenderers/View/Droid/MainActivity.cs
old mode 100755
new mode 100644
index fd6ad5885d..6f80b8f7c4
--- a/CustomRenderers/View/Droid/MainActivity.cs
+++ b/CustomRenderers/View/Droid/MainActivity.cs
@@ -1,24 +1,16 @@
-using System;
-
-using Android.App;
-using Android.Content;
+using Android.App;
using Android.Content.PM;
-using Android.Runtime;
-using Android.Views;
-using Android.Widget;
using Android.OS;
namespace CustomRenderer.Droid
{
- [Activity (Label = "CustomRenderer.Droid", Icon = "@drawable/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
+ [Activity (Label = "CustomRenderer.Droid", Icon = "@drawable/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
-
global::Xamarin.Forms.Forms.Init (this, bundle);
-
LoadApplication (new App ());
}
}
diff --git a/CustomRenderers/View/Droid/Properties/AndroidManifest.xml b/CustomRenderers/View/Droid/Properties/AndroidManifest.xml
old mode 100755
new mode 100644
index 85ab804c46..eed106b899
--- a/CustomRenderers/View/Droid/Properties/AndroidManifest.xml
+++ b/CustomRenderers/View/Droid/Properties/AndroidManifest.xml
@@ -1,7 +1,6 @@
-
-
-
+
+
\ No newline at end of file
diff --git a/CustomRenderers/View/Droid/Resources/Resource.designer.cs b/CustomRenderers/View/Droid/Resources/Resource.designer.cs
index 7e57160cc2..293b2f061d 100644
--- a/CustomRenderers/View/Droid/Resources/Resource.designer.cs
+++ b/CustomRenderers/View/Droid/Resources/Resource.designer.cs
@@ -8322,361 +8322,361 @@ public partial class Id
public const int buttonPanel = 2131230762;
// aapt resource value: 0x7F08002B
- public const int cancel_action = 2131230763;
+ public const int cameratexture = 2131230763;
// aapt resource value: 0x7F08002C
- public const int center = 2131230764;
+ public const int cancel_action = 2131230764;
// aapt resource value: 0x7F08002D
- public const int center_horizontal = 2131230765;
+ public const int center = 2131230765;
// aapt resource value: 0x7F08002E
- public const int center_vertical = 2131230766;
+ public const int center_horizontal = 2131230766;
// aapt resource value: 0x7F08002F
- public const int checkbox = 2131230767;
+ public const int center_vertical = 2131230767;
// aapt resource value: 0x7F080030
- public const int chronometer = 2131230768;
+ public const int checkbox = 2131230768;
// aapt resource value: 0x7F080031
- public const int clip_horizontal = 2131230769;
+ public const int chronometer = 2131230769;
// aapt resource value: 0x7F080032
- public const int clip_vertical = 2131230770;
+ public const int clip_horizontal = 2131230770;
// aapt resource value: 0x7F080033
- public const int collapseActionView = 2131230771;
+ public const int clip_vertical = 2131230771;
// aapt resource value: 0x7F080034
- public const int container = 2131230772;
+ public const int collapseActionView = 2131230772;
// aapt resource value: 0x7F080035
- public const int content = 2131230773;
+ public const int container = 2131230773;
// aapt resource value: 0x7F080036
- public const int contentPanel = 2131230774;
+ public const int content = 2131230774;
// aapt resource value: 0x7F080037
- public const int coordinator = 2131230775;
+ public const int contentPanel = 2131230775;
+
+ // aapt resource value: 0x7F080038
+ public const int coordinator = 2131230776;
// aapt resource value: 0x7F080001
public const int CTRL = 2131230721;
- // aapt resource value: 0x7F080038
- public const int custom = 2131230776;
-
// aapt resource value: 0x7F080039
- public const int customPanel = 2131230777;
+ public const int custom = 2131230777;
// aapt resource value: 0x7F08003A
- public const int decor_content_parent = 2131230778;
+ public const int customPanel = 2131230778;
// aapt resource value: 0x7F08003B
- public const int default_activity_button = 2131230779;
+ public const int decor_content_parent = 2131230779;
// aapt resource value: 0x7F08003C
- public const int design_bottom_sheet = 2131230780;
+ public const int default_activity_button = 2131230780;
// aapt resource value: 0x7F08003D
- public const int design_menu_item_action_area = 2131230781;
+ public const int design_bottom_sheet = 2131230781;
// aapt resource value: 0x7F08003E
- public const int design_menu_item_action_area_stub = 2131230782;
+ public const int design_menu_item_action_area = 2131230782;
// aapt resource value: 0x7F08003F
- public const int design_menu_item_text = 2131230783;
+ public const int design_menu_item_action_area_stub = 2131230783;
// aapt resource value: 0x7F080040
- public const int design_navigation_view = 2131230784;
+ public const int design_menu_item_text = 2131230784;
// aapt resource value: 0x7F080041
- public const int disableHome = 2131230785;
+ public const int design_navigation_view = 2131230785;
// aapt resource value: 0x7F080042
- public const int edit_query = 2131230786;
+ public const int disableHome = 2131230786;
// aapt resource value: 0x7F080043
- public const int end = 2131230787;
+ public const int edit_query = 2131230787;
// aapt resource value: 0x7F080044
- public const int end_padder = 2131230788;
+ public const int end = 2131230788;
// aapt resource value: 0x7F080045
- public const int enterAlways = 2131230789;
+ public const int end_padder = 2131230789;
// aapt resource value: 0x7F080046
- public const int enterAlwaysCollapsed = 2131230790;
+ public const int enterAlways = 2131230790;
// aapt resource value: 0x7F080047
- public const int exitUntilCollapsed = 2131230791;
-
- // aapt resource value: 0x7F080049
- public const int expanded_menu = 2131230793;
+ public const int enterAlwaysCollapsed = 2131230791;
// aapt resource value: 0x7F080048
- public const int expand_activities_button = 2131230792;
+ public const int exitUntilCollapsed = 2131230792;
// aapt resource value: 0x7F08004A
- public const int fill = 2131230794;
+ public const int expanded_menu = 2131230794;
- // aapt resource value: 0x7F08004D
- public const int filled = 2131230797;
+ // aapt resource value: 0x7F080049
+ public const int expand_activities_button = 2131230793;
// aapt resource value: 0x7F08004B
- public const int fill_horizontal = 2131230795;
+ public const int fill = 2131230795;
+
+ // aapt resource value: 0x7F08004E
+ public const int filled = 2131230798;
// aapt resource value: 0x7F08004C
- public const int fill_vertical = 2131230796;
+ public const int fill_horizontal = 2131230796;
- // aapt resource value: 0x7F08004E
- public const int @fixed = 2131230798;
+ // aapt resource value: 0x7F08004D
+ public const int fill_vertical = 2131230797;
// aapt resource value: 0x7F08004F
- public const int flyoutcontent_appbar = 2131230799;
+ public const int @fixed = 2131230799;
// aapt resource value: 0x7F080050
- public const int flyoutcontent_recycler = 2131230800;
+ public const int flyoutcontent_appbar = 2131230800;
// aapt resource value: 0x7F080051
- public const int forever = 2131230801;
+ public const int flyoutcontent_recycler = 2131230801;
+
+ // aapt resource value: 0x7F080052
+ public const int forever = 2131230802;
// aapt resource value: 0x7F080002
public const int FUNCTION = 2131230722;
- // aapt resource value: 0x7F080052
- public const int ghost_view = 2131230802;
-
// aapt resource value: 0x7F080053
- public const int group_divider = 2131230803;
+ public const int ghost_view = 2131230803;
// aapt resource value: 0x7F080054
- public const int home = 2131230804;
+ public const int group_divider = 2131230804;
// aapt resource value: 0x7F080055
- public const int homeAsUp = 2131230805;
+ public const int home = 2131230805;
// aapt resource value: 0x7F080056
- public const int icon = 2131230806;
+ public const int homeAsUp = 2131230806;
// aapt resource value: 0x7F080057
- public const int icon_group = 2131230807;
+ public const int icon = 2131230807;
// aapt resource value: 0x7F080058
- public const int ifRoom = 2131230808;
+ public const int icon_group = 2131230808;
// aapt resource value: 0x7F080059
- public const int image = 2131230809;
+ public const int ifRoom = 2131230809;
// aapt resource value: 0x7F08005A
- public const int info = 2131230810;
+ public const int image = 2131230810;
// aapt resource value: 0x7F08005B
- public const int italic = 2131230811;
+ public const int info = 2131230811;
// aapt resource value: 0x7F08005C
- public const int item_touch_helper_previous_elevation = 2131230812;
+ public const int italic = 2131230812;
// aapt resource value: 0x7F08005D
- public const int labeled = 2131230813;
+ public const int item_touch_helper_previous_elevation = 2131230813;
// aapt resource value: 0x7F08005E
- public const int largeLabel = 2131230814;
+ public const int labeled = 2131230814;
// aapt resource value: 0x7F08005F
- public const int left = 2131230815;
+ public const int largeLabel = 2131230815;
// aapt resource value: 0x7F080060
- public const int line1 = 2131230816;
+ public const int left = 2131230816;
// aapt resource value: 0x7F080061
- public const int line3 = 2131230817;
+ public const int line1 = 2131230817;
// aapt resource value: 0x7F080062
- public const int listMode = 2131230818;
+ public const int line3 = 2131230818;
// aapt resource value: 0x7F080063
- public const int list_item = 2131230819;
+ public const int listMode = 2131230819;
// aapt resource value: 0x7F080064
- public const int main_appbar = 2131230820;
+ public const int list_item = 2131230820;
// aapt resource value: 0x7F080065
- public const int main_tablayout = 2131230821;
+ public const int main_appbar = 2131230821;
// aapt resource value: 0x7F080066
- public const int main_toolbar = 2131230822;
+ public const int main_tablayout = 2131230822;
// aapt resource value: 0x7F080067
- public const int main_viewpager = 2131230823;
+ public const int main_toolbar = 2131230823;
// aapt resource value: 0x7F080068
- public const int masked = 2131230824;
+ public const int main_viewpager = 2131230824;
// aapt resource value: 0x7F080069
- public const int media_actions = 2131230825;
+ public const int masked = 2131230825;
// aapt resource value: 0x7F08006A
- public const int message = 2131230826;
+ public const int media_actions = 2131230826;
+
+ // aapt resource value: 0x7F08006B
+ public const int message = 2131230827;
// aapt resource value: 0x7F080003
public const int META = 2131230723;
- // aapt resource value: 0x7F08006B
- public const int middle = 2131230827;
-
// aapt resource value: 0x7F08006C
- public const int mini = 2131230828;
+ public const int middle = 2131230828;
// aapt resource value: 0x7F08006D
- public const int mtrl_child_content_container = 2131230829;
+ public const int mini = 2131230829;
// aapt resource value: 0x7F08006E
- public const int mtrl_internal_children_alpha_tag = 2131230830;
+ public const int mtrl_child_content_container = 2131230830;
// aapt resource value: 0x7F08006F
- public const int multiply = 2131230831;
+ public const int mtrl_internal_children_alpha_tag = 2131230831;
// aapt resource value: 0x7F080070
- public const int navigation_header_container = 2131230832;
+ public const int multiply = 2131230832;
// aapt resource value: 0x7F080071
- public const int never = 2131230833;
+ public const int navigation_header_container = 2131230833;
// aapt resource value: 0x7F080072
- public const int none = 2131230834;
+ public const int never = 2131230834;
// aapt resource value: 0x7F080073
- public const int normal = 2131230835;
+ public const int none = 2131230835;
// aapt resource value: 0x7F080074
- public const int notification_background = 2131230836;
+ public const int normal = 2131230836;
// aapt resource value: 0x7F080075
- public const int notification_main_column = 2131230837;
+ public const int notification_background = 2131230837;
// aapt resource value: 0x7F080076
- public const int notification_main_column_container = 2131230838;
+ public const int notification_main_column = 2131230838;
// aapt resource value: 0x7F080077
- public const int outline = 2131230839;
+ public const int notification_main_column_container = 2131230839;
// aapt resource value: 0x7F080078
- public const int parallax = 2131230840;
+ public const int outline = 2131230840;
// aapt resource value: 0x7F080079
- public const int parentPanel = 2131230841;
+ public const int parallax = 2131230841;
// aapt resource value: 0x7F08007A
- public const int parent_matrix = 2131230842;
+ public const int parentPanel = 2131230842;
// aapt resource value: 0x7F08007B
- public const int pin = 2131230843;
+ public const int parent_matrix = 2131230843;
// aapt resource value: 0x7F08007C
- public const int progress_circular = 2131230844;
+ public const int pin = 2131230844;
// aapt resource value: 0x7F08007D
- public const int progress_horizontal = 2131230845;
+ public const int progress_circular = 2131230845;
// aapt resource value: 0x7F08007E
- public const int radio = 2131230846;
+ public const int progress_horizontal = 2131230846;
// aapt resource value: 0x7F08007F
- public const int right = 2131230847;
+ public const int radio = 2131230847;
// aapt resource value: 0x7F080080
- public const int right_icon = 2131230848;
+ public const int right = 2131230848;
// aapt resource value: 0x7F080081
- public const int right_side = 2131230849;
+ public const int right_icon = 2131230849;
// aapt resource value: 0x7F080082
- public const int save_image_matrix = 2131230850;
+ public const int right_side = 2131230850;
// aapt resource value: 0x7F080083
- public const int save_non_transition_alpha = 2131230851;
+ public const int save_image_matrix = 2131230851;
// aapt resource value: 0x7F080084
- public const int save_scale_type = 2131230852;
+ public const int save_non_transition_alpha = 2131230852;
// aapt resource value: 0x7F080085
- public const int screen = 2131230853;
+ public const int save_scale_type = 2131230853;
// aapt resource value: 0x7F080086
- public const int scroll = 2131230854;
-
- // aapt resource value: 0x7F08008A
- public const int scrollable = 2131230858;
+ public const int screen = 2131230854;
// aapt resource value: 0x7F080087
- public const int scrollIndicatorDown = 2131230855;
+ public const int scroll = 2131230855;
+
+ // aapt resource value: 0x7F08008B
+ public const int scrollable = 2131230859;
// aapt resource value: 0x7F080088
- public const int scrollIndicatorUp = 2131230856;
+ public const int scrollIndicatorDown = 2131230856;
// aapt resource value: 0x7F080089
- public const int scrollView = 2131230857;
+ public const int scrollIndicatorUp = 2131230857;
- // aapt resource value: 0x7F08008B
- public const int search_badge = 2131230859;
+ // aapt resource value: 0x7F08008A
+ public const int scrollView = 2131230858;
// aapt resource value: 0x7F08008C
- public const int search_bar = 2131230860;
+ public const int search_badge = 2131230860;
// aapt resource value: 0x7F08008D
- public const int search_button = 2131230861;
+ public const int search_bar = 2131230861;
// aapt resource value: 0x7F08008E
- public const int search_close_btn = 2131230862;
+ public const int search_button = 2131230862;
// aapt resource value: 0x7F08008F
- public const int search_edit_frame = 2131230863;
+ public const int search_close_btn = 2131230863;
// aapt resource value: 0x7F080090
- public const int search_go_btn = 2131230864;
+ public const int search_edit_frame = 2131230864;
// aapt resource value: 0x7F080091
- public const int search_mag_icon = 2131230865;
+ public const int search_go_btn = 2131230865;
// aapt resource value: 0x7F080092
- public const int search_plate = 2131230866;
+ public const int search_mag_icon = 2131230866;
// aapt resource value: 0x7F080093
- public const int search_src_text = 2131230867;
+ public const int search_plate = 2131230867;
// aapt resource value: 0x7F080094
- public const int search_voice_btn = 2131230868;
-
- // aapt resource value: 0x7F080096
- public const int selected = 2131230870;
+ public const int search_src_text = 2131230868;
// aapt resource value: 0x7F080095
- public const int select_dialog_listview = 2131230869;
+ public const int search_voice_btn = 2131230869;
// aapt resource value: 0x7F080097
- public const int shellcontent_appbar = 2131230871;
+ public const int selected = 2131230871;
+
+ // aapt resource value: 0x7F080096
+ public const int select_dialog_listview = 2131230870;
// aapt resource value: 0x7F080098
- public const int shellcontent_toolbar = 2131230872;
+ public const int shellcontent_appbar = 2131230872;
+
+ // aapt resource value: 0x7F080099
+ public const int shellcontent_toolbar = 2131230873;
// aapt resource value: 0x7F080004
public const int SHIFT = 2131230724;
- // aapt resource value: 0x7F080099
- public const int shortcut = 2131230873;
-
// aapt resource value: 0x7F08009A
- public const int showCustom = 2131230874;
+ public const int shortcut = 2131230874;
// aapt resource value: 0x7F08009B
- public const int showHome = 2131230875;
+ public const int showCustom = 2131230875;
// aapt resource value: 0x7F08009C
- public const int showTitle = 2131230876;
+ public const int showHome = 2131230876;
// aapt resource value: 0x7F08009D
- public const int sliding_tabs = 2131230877;
+ public const int showTitle = 2131230877;
// aapt resource value: 0x7F08009E
public const int smallLabel = 2131230878;
@@ -8778,55 +8778,52 @@ public partial class Id
public const int title_template = 2131230909;
// aapt resource value: 0x7F0800BE
- public const int toolbar = 2131230910;
+ public const int top = 2131230910;
// aapt resource value: 0x7F0800BF
- public const int top = 2131230911;
+ public const int topPanel = 2131230911;
// aapt resource value: 0x7F0800C0
- public const int topPanel = 2131230912;
+ public const int touch_outside = 2131230912;
// aapt resource value: 0x7F0800C1
- public const int touch_outside = 2131230913;
+ public const int transition_current_scene = 2131230913;
// aapt resource value: 0x7F0800C2
- public const int transition_current_scene = 2131230914;
+ public const int transition_layout_save = 2131230914;
// aapt resource value: 0x7F0800C3
- public const int transition_layout_save = 2131230915;
+ public const int transition_position = 2131230915;
// aapt resource value: 0x7F0800C4
- public const int transition_position = 2131230916;
+ public const int transition_scene_layoutid_cache = 2131230916;
// aapt resource value: 0x7F0800C5
- public const int transition_scene_layoutid_cache = 2131230917;
+ public const int transition_transform = 2131230917;
// aapt resource value: 0x7F0800C6
- public const int transition_transform = 2131230918;
+ public const int uniform = 2131230918;
// aapt resource value: 0x7F0800C7
- public const int uniform = 2131230919;
+ public const int unlabeled = 2131230919;
// aapt resource value: 0x7F0800C8
- public const int unlabeled = 2131230920;
+ public const int up = 2131230920;
// aapt resource value: 0x7F0800C9
- public const int up = 2131230921;
+ public const int useLogo = 2131230921;
// aapt resource value: 0x7F0800CA
- public const int useLogo = 2131230922;
+ public const int view_offset_helper = 2131230922;
// aapt resource value: 0x7F0800CB
- public const int view_offset_helper = 2131230923;
+ public const int visible = 2131230923;
// aapt resource value: 0x7F0800CC
- public const int visible = 2131230924;
+ public const int withText = 2131230924;
// aapt resource value: 0x7F0800CD
- public const int withText = 2131230925;
-
- // aapt resource value: 0x7F0800CE
- public const int wrap_content = 2131230926;
+ public const int wrap_content = 2131230925;
static Id()
{
@@ -9018,124 +9015,121 @@ public partial class Layout
public const int browser_actions_context_menu_row = 2131427358;
// aapt resource value: 0x7F0B001F
- public const int design_bottom_navigation_item = 2131427359;
+ public const int CameraFragment = 2131427359;
// aapt resource value: 0x7F0B0020
- public const int design_bottom_sheet_dialog = 2131427360;
+ public const int design_bottom_navigation_item = 2131427360;
// aapt resource value: 0x7F0B0021
- public const int design_layout_snackbar = 2131427361;
+ public const int design_bottom_sheet_dialog = 2131427361;
// aapt resource value: 0x7F0B0022
- public const int design_layout_snackbar_include = 2131427362;
+ public const int design_layout_snackbar = 2131427362;
// aapt resource value: 0x7F0B0023
- public const int design_layout_tab_icon = 2131427363;
+ public const int design_layout_snackbar_include = 2131427363;
// aapt resource value: 0x7F0B0024
- public const int design_layout_tab_text = 2131427364;
+ public const int design_layout_tab_icon = 2131427364;
// aapt resource value: 0x7F0B0025
- public const int design_menu_item_action_area = 2131427365;
+ public const int design_layout_tab_text = 2131427365;
// aapt resource value: 0x7F0B0026
- public const int design_navigation_item = 2131427366;
+ public const int design_menu_item_action_area = 2131427366;
// aapt resource value: 0x7F0B0027
- public const int design_navigation_item_header = 2131427367;
+ public const int design_navigation_item = 2131427367;
// aapt resource value: 0x7F0B0028
- public const int design_navigation_item_separator = 2131427368;
+ public const int design_navigation_item_header = 2131427368;
// aapt resource value: 0x7F0B0029
- public const int design_navigation_item_subheader = 2131427369;
+ public const int design_navigation_item_separator = 2131427369;
// aapt resource value: 0x7F0B002A
- public const int design_navigation_menu = 2131427370;
+ public const int design_navigation_item_subheader = 2131427370;
// aapt resource value: 0x7F0B002B
- public const int design_navigation_menu_item = 2131427371;
+ public const int design_navigation_menu = 2131427371;
// aapt resource value: 0x7F0B002C
- public const int design_text_input_password_icon = 2131427372;
+ public const int design_navigation_menu_item = 2131427372;
// aapt resource value: 0x7F0B002D
- public const int FlyoutContent = 2131427373;
+ public const int design_text_input_password_icon = 2131427373;
// aapt resource value: 0x7F0B002E
- public const int mtrl_layout_snackbar = 2131427374;
+ public const int FlyoutContent = 2131427374;
// aapt resource value: 0x7F0B002F
- public const int mtrl_layout_snackbar_include = 2131427375;
+ public const int mtrl_layout_snackbar = 2131427375;
// aapt resource value: 0x7F0B0030
- public const int notification_action = 2131427376;
+ public const int mtrl_layout_snackbar_include = 2131427376;
// aapt resource value: 0x7F0B0031
- public const int notification_action_tombstone = 2131427377;
+ public const int notification_action = 2131427377;
// aapt resource value: 0x7F0B0032
- public const int notification_media_action = 2131427378;
+ public const int notification_action_tombstone = 2131427378;
// aapt resource value: 0x7F0B0033
- public const int notification_media_cancel_action = 2131427379;
+ public const int notification_media_action = 2131427379;
// aapt resource value: 0x7F0B0034
- public const int notification_template_big_media = 2131427380;
+ public const int notification_media_cancel_action = 2131427380;
// aapt resource value: 0x7F0B0035
- public const int notification_template_big_media_custom = 2131427381;
+ public const int notification_template_big_media = 2131427381;
// aapt resource value: 0x7F0B0036
- public const int notification_template_big_media_narrow = 2131427382;
+ public const int notification_template_big_media_custom = 2131427382;
// aapt resource value: 0x7F0B0037
- public const int notification_template_big_media_narrow_custom = 2131427383;
+ public const int notification_template_big_media_narrow = 2131427383;
// aapt resource value: 0x7F0B0038
- public const int notification_template_custom_big = 2131427384;
+ public const int notification_template_big_media_narrow_custom = 2131427384;
// aapt resource value: 0x7F0B0039
- public const int notification_template_icon_group = 2131427385;
+ public const int notification_template_custom_big = 2131427385;
// aapt resource value: 0x7F0B003A
- public const int notification_template_lines_media = 2131427386;
+ public const int notification_template_icon_group = 2131427386;
// aapt resource value: 0x7F0B003B
- public const int notification_template_media = 2131427387;
+ public const int notification_template_lines_media = 2131427387;
// aapt resource value: 0x7F0B003C
- public const int notification_template_media_custom = 2131427388;
+ public const int notification_template_media = 2131427388;
// aapt resource value: 0x7F0B003D
- public const int notification_template_part_chronometer = 2131427389;
+ public const int notification_template_media_custom = 2131427389;
// aapt resource value: 0x7F0B003E
- public const int notification_template_part_time = 2131427390;
+ public const int notification_template_part_chronometer = 2131427390;
// aapt resource value: 0x7F0B003F
- public const int RootLayout = 2131427391;
+ public const int notification_template_part_time = 2131427391;
// aapt resource value: 0x7F0B0040
- public const int select_dialog_item_material = 2131427392;
+ public const int RootLayout = 2131427392;
// aapt resource value: 0x7F0B0041
- public const int select_dialog_multichoice_material = 2131427393;
+ public const int select_dialog_item_material = 2131427393;
// aapt resource value: 0x7F0B0042
- public const int select_dialog_singlechoice_material = 2131427394;
+ public const int select_dialog_multichoice_material = 2131427394;
// aapt resource value: 0x7F0B0043
- public const int ShellContent = 2131427395;
+ public const int select_dialog_singlechoice_material = 2131427395;
// aapt resource value: 0x7F0B0044
- public const int support_simple_spinner_dropdown_item = 2131427396;
+ public const int ShellContent = 2131427396;
// aapt resource value: 0x7F0B0045
- public const int Tabbar = 2131427397;
-
- // aapt resource value: 0x7F0B0046
- public const int Toolbar = 2131427398;
+ public const int support_simple_spinner_dropdown_item = 2131427397;
static Layout()
{
diff --git a/CustomRenderers/View/Droid/Resources/layout/CameraFragment.xml b/CustomRenderers/View/Droid/Resources/layout/CameraFragment.xml
new file mode 100644
index 0000000000..7188bc19a7
--- /dev/null
+++ b/CustomRenderers/View/Droid/Resources/layout/CameraFragment.xml
@@ -0,0 +1,10 @@
+
+
+
diff --git a/CustomRenderers/View/Droid/Resources/layout/Tabbar.axml b/CustomRenderers/View/Droid/Resources/layout/Tabbar.axml
deleted file mode 100644
index 1187962a08..0000000000
--- a/CustomRenderers/View/Droid/Resources/layout/Tabbar.axml
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
\ No newline at end of file
diff --git a/CustomRenderers/View/Droid/Resources/layout/Toolbar.axml b/CustomRenderers/View/Droid/Resources/layout/Toolbar.axml
deleted file mode 100644
index eee97c6941..0000000000
--- a/CustomRenderers/View/Droid/Resources/layout/Toolbar.axml
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
\ No newline at end of file
diff --git a/CustomRenderers/View/UWP/CustomRenderer.UWP.csproj b/CustomRenderers/View/UWP/CustomRenderer.UWP.csproj
index 409cc2a124..84bffbfd89 100755
--- a/CustomRenderers/View/UWP/CustomRenderer.UWP.csproj
+++ b/CustomRenderers/View/UWP/CustomRenderer.UWP.csproj
@@ -137,4 +137,4 @@
14.0
-
\ No newline at end of file
+
diff --git a/CustomRenderers/View/iOS/CustomRenderer.iOS.csproj b/CustomRenderers/View/iOS/CustomRenderer.iOS.csproj
index 880e734ed3..7b543ce274 100644
--- a/CustomRenderers/View/iOS/CustomRenderer.iOS.csproj
+++ b/CustomRenderers/View/iOS/CustomRenderer.iOS.csproj
@@ -21,7 +21,7 @@
4
false
x86_64
- SdkOnly
+ None
true
true
iPhone Developer
@@ -116,4 +116,4 @@
-
\ No newline at end of file
+