我正在使用Xamarin.Forms开发Android和IOS应用程序。首先,我想说,我是Xamarin的全新手。在我的应用程序中,我正在尝试创建自定义相机视图。所以,我知道我必须使用内容页面渲染器功能开发特定于每个平台的自定义摄像机视图。
首先,我首先尝试为Android实现相机功能。当我创建自定义相机页面时,我需要设置布局并使用我的代码中的资源ID检索一些视图。但是当我检索引用Android项目中资源ID的视图时。它不起作用。请看下面的代码。
在主要的Xamarin表单项目中,我为Camera创建了一个视图页面,就像这样。这是xaml。
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MementoApp.Views.CameraPage">
<ContentPage.Content>
</ContentPage.Content>
</ContentPage>
这是xaml.cs
namespace MementoApp.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class CameraPage : ContentPage
{
public CameraPage ()
{
InitializeComponent ();
}
}
}
然后在android项目中,我在Resource文件夹下创建了一个名为Camera.axml
的新axml布局文件<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1">
<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" />
</LinearLayout>
这是Android项目中我的CameraPageRenderer类的完整代码
[assembly: ExportRenderer(typeof(CameraPage), typeof(CameraPageRenderer))]
namespace MementoApp.Droid
{
public class CameraPageRenderer: PageRenderer ,TextureView.ISurfaceTextureListener
{
Android.Hardware.Camera camera;
global::Android.Widget.Button takePhotoButton;
global::Android.Widget.Button toggleFlashButton;
global::Android.Widget.Button switchCameraButton;
global::Android.Views.View view;
Activity activity;
CameraFacing cameraType;
TextureView textureView;
SurfaceTexture surfaceTexture;
bool flashOn;
public CameraPageRenderer(Context context) : base(context)
{
this.activity = context as Activity;
}
protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
{
base.OnElementChanged(e);
if (e.OldElement != null || Element == null)
{
return;
}
try
{
SetupUserInterface();
SetupEventHandlers();
AddView(view);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(@" ERROR: ", ex.Message);
}
}
void SetupUserInterface()
{
activity = this.Context as Activity;
view = activity.LayoutInflater.Inflate(Resource.Layout.Camera, this, false);
cameraType = CameraFacing.Back;
textureView = view.FindViewById<TextureView>(Resource.Id.textureView);
textureView.SurfaceTextureListener = this;
}
void SetupEventHandlers()
{
takePhotoButton = view.FindViewById<global::Android.Widget.Button>(Resource.Id.takePhotoButton);
takePhotoButton.Click += TakePhotoButtonTapped;
switchCameraButton = view.FindViewById<global::Android.Widget.Button>(Resource.Id.switchCameraButton);
switchCameraButton.Click += SwitchCameraButtonTapped;
toggleFlashButton = view.FindViewById<global::Android.Widget.Button>(Resource.Id.toggleFlashButton);
toggleFlashButton.Click += ToggleFlashButtonTapped;
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
var msw = MeasureSpec.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly);
var msh = MeasureSpec.MakeMeasureSpec(b - t, MeasureSpecMode.Exactly);
view.Measure(msw, msh);
view.Layout(0, 0, r - l, b - t);
}
public void OnSurfaceTextureUpdated(SurfaceTexture surface)
{
}
public void OnSurfaceTextureAvailable(SurfaceTexture surface, int width, int height)
{
camera = global::Android.Hardware.Camera.Open((int)cameraType);
textureView.LayoutParameters = new FrameLayout.LayoutParams(width, height);
surfaceTexture = surface;
camera.SetPreviewTexture(surface);
PrepareAndStartCamera();
}
public bool OnSurfaceTextureDestroyed(SurfaceTexture surface)
{
camera.StopPreview();
camera.Release();
return true;
}
public void OnSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height)
{
PrepareAndStartCamera();
}
void PrepareAndStartCamera()
{
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();
}
void ToggleFlashButtonTapped(object sender, EventArgs e)
{
flashOn = !flashOn;
if (flashOn)
{
if (cameraType == CameraFacing.Back)
{
toggleFlashButton.SetBackgroundResource(Resource.Drawable.FlashButton);
cameraType = CameraFacing.Back;
camera.StopPreview();
camera.Release();
camera = global::Android.Hardware.Camera.Open((int)cameraType);
var parameters = camera.GetParameters();
parameters.FlashMode = global::Android.Hardware.Camera.Parameters.FlashModeTorch;
camera.SetParameters(parameters);
camera.SetPreviewTexture(surfaceTexture);
PrepareAndStartCamera();
}
}
else
{
toggleFlashButton.SetBackgroundResource(Resource.Drawable.NoFlashButton);
camera.StopPreview();
camera.Release();
camera = global::Android.Hardware.Camera.Open((int)cameraType);
var parameters = camera.GetParameters();
parameters.FlashMode = global::Android.Hardware.Camera.Parameters.FlashModeOff;
camera.SetParameters(parameters);
camera.SetPreviewTexture(surfaceTexture);
PrepareAndStartCamera();
}
}
void SwitchCameraButtonTapped(object sender, EventArgs e)
{
if (cameraType == CameraFacing.Front)
{
cameraType = CameraFacing.Back;
camera.StopPreview();
camera.Release();
camera = global::Android.Hardware.Camera.Open((int)cameraType);
camera.SetPreviewTexture(surfaceTexture);
PrepareAndStartCamera();
}
else
{
cameraType = CameraFacing.Front;
camera.StopPreview();
camera.Release();
camera = global::Android.Hardware.Camera.Open((int)cameraType);
camera.SetPreviewTexture(surfaceTexture);
PrepareAndStartCamera();
}
}
async void TakePhotoButtonTapped(object sender, EventArgs e)
{
camera.StopPreview();
var image = textureView.Bitmap;
try
{
var absolutePath = Android.OS.Environment.GetExternalStoragePublicDirectory(Android.OS.Environment.DirectoryDcim).AbsolutePath;
var folderPath = absolutePath + "/Camera";
var filePath = System.IO.Path.Combine(folderPath, string.Format("photo_{0}.jpg", Guid.NewGuid()));
var fileStream = new FileStream(filePath, FileMode.Create);
await image.CompressAsync(Bitmap.CompressFormat.Jpeg, 50, fileStream);
fileStream.Close();
image.Recycle();
var intent = new Android.Content.Intent(Android.Content.Intent.ActionMediaScannerScanFile);
var file = new Java.IO.File(filePath);
var uri = Android.Net.Uri.FromFile(file);
intent.SetData(uri);
activity.SendBroadcast(intent);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(@" ", ex.Message);
}
camera.StartPreview();
}
}
}
问题是当我使用资源ID从c#代码中检索视图时,它说的是资源.Id&#39;不包含&#34; view id&#34;的定义如下面的截图。
{{3}}
为什么会抛出这个错误?我的代码出了什么问题?