我有 Xamarin Forms 解决方案,在 Xamarin Droid 项目中,我有扩展 ContentView 的类 CustomCameraScanView 的自定义渲染器。此 CustomCameraScanView 应在 5.0 (Lollipop) 之前的 Android 上使用 Camera(旧 API),并在 5.0 及更高版本中使用 Camera2(新 API)。如何创建将在不同版本的操作系统上使用的两个渲染器:CustomCameraScanViewRenderer_Droid4 和 CustomCameraScanViewRenderer_Droid5?
我的 CustomCameraScanViewRenderer_Droid4 看起来像这样:
[assembly: ExportRenderer(typeof(CustomCameraScanView), typeof(CustomCameraScanViewRenderer_Droid4))]
namespace Genea.Droid.Renderers
{
public class CustomCameraScanViewRenderer_Droid4 : ViewRenderer,
ISurfaceTextureListener,
ISurfaceHolderCallback,
Android.Hardware.Camera.IPreviewCallback,
Android.Hardware.Camera.IPictureCallback,
Android.Hardware.Camera.IShutterCallback
{
}
}
最佳答案
不幸的是,目前在 Xamarin-Forms 中无法在运行时注册自定义渲染器。更多详情可以查看此forum link 。但您可以做的是使用 OnPlatform 和构建版本号在运行时解析控件。
我当然会首先推荐 @luccas-clezar 建议的条件编译方法;但如果这不是一个选项,那么您可以尝试使用以下步骤在运行时解析您的控件(以及渲染器)。
步骤:
创建一个简单的合约来解析当前的 API 值 - 在表单项目中
public interface IBuildVersion { int Number { get; } }
为Android平台实现
public class AndroidBuildVersion : IBuildVersion { public int Number { get { return ((int)Android.OS.Build.VERSION.SdkInt); } } }
注册 DependencyService
[assembly: Xamarin.Forms.Dependency (typeof (AndroidBuildVersion))]
子类化您的
CustomCameraScanView
分为两种派生类型 - 在表单项目中public class CustomCameraScanView_Droid4 : CustomCameraScanView { } public class CustomCameraScanView_Droid5 : CustomCameraScanView { }
在 Android 项目中设置渲染器
[assembly: ExportRenderer(typeof(CustomCameraScanView_Droid4), typeof(CustomCameraScanViewRenderer_Droid4))]
并且,
[assembly: ExportRenderer(typeof(CustomCameraScanView_Droid5), typeof(CustomCameraScanViewRenderer_Droid5))]
创建自定义控件以在运行时解析 - 使用
OnPlatform
- 在表单项目中public class CameraScanContentView : Xamarin.Forms.ContentView { public CameraScanContentView() { this.Content = Device.OnPlatform( iOS: new CustomCameraScanView(), Android: DependencyService.Get<IBuildVersion>().Number < 21 ? ((CustomCameraScanView)new CustomCameraScanView_Droid4()) : ((CustomCameraScanView)new CustomCameraScanView_Droid5()), WinPhone: new CustomCameraScanView() ); } }
并且,XAML 用法将如下所示
<local:CameraScanContentView />
更新 05/24
我不相信 Xamarin-Forms 像 WPF 那样支持“属性值”继承 - 因此将值从父控件传播到子控件有点棘手。
一种选择是将这些值级联回 CustomCameraScanView
来自CameraScanContentView
通过定义可绑定(bind)属性(推荐):
public class CameraScanContentView : Xamarin.Forms.ContentView
{
public CameraScanContentView()
{
CustomCameraScanView scannerCtrl = null;
switch (Device.RuntimePlatform)
{
case Device.Android:
scannerCtrl = DependencyService.Get<IBuildVersion>().Number < 21
? ((CustomCameraScanView)new CustomCameraScanView_Droid4())
: ((CustomCameraScanView)new CustomCameraScanView_Droid5());
break;
default:
scannerCtrl = new CustomCameraScanView();
break;
}
scannerCtrl.SetBinding(CustomCameraScanView.IsScanningProperty, new Binding(nameof(IsScanning), source: this));
scannerCtrl.SetBinding(CustomCameraScanView.IsTakingImageProperty, new Binding(nameof(IsTakingImage), source: this));
scannerCtrl.SetBinding(CustomCameraScanView.IsFlashlightOnProperty, new Binding(nameof(IsFlashlightOn), source: this));
Content = scannerCtrl;
}
public static readonly BindableProperty IsScanningProperty = BindableProperty.Create("IsScanning", typeof(bool), typeof(CameraScanContentView), false);
public static readonly BindableProperty IsTakingImageProperty = BindableProperty.Create("IsTakingImage", typeof(bool), typeof(CameraScanContentView), false);
public static readonly BindableProperty IsFlashlightOnProperty = BindableProperty.Create("IsFlashlightOn", typeof(bool), typeof(CameraScanContentView), false);
public bool IsScanning
{
get { return (bool)GetValue(IsScanningProperty); }
set { SetValue(IsScanningProperty, value); }
}
public bool IsTakingImage
{
get { return (bool)GetValue(IsTakingImageProperty); }
set { SetValue(IsTakingImageProperty, value); }
}
public bool IsFlashlightOn
{
get { return (bool)GetValue(IsFlashlightOnProperty); }
set { SetValue(IsFlashlightOnProperty, value); }
}
}
XAML 用法将如下所示
<local:CameraScanContentView IsScanning="{Binding IsScanning}" IsFlashlightOn="{Binding IsFlashlightOn}" IsTakingImage="{Binding IsTakingImage}" />
或者,您可以手动定义绑定(bind)表达式,如下所示(不推荐,因为它假设 View 模型上的属性名称不会更改):
public class CameraScanContentView : Xamarin.Forms.ContentView
{
public CameraScanContentView()
{
CustomCameraScanView scannerCtrl = null;
switch (Device.RuntimePlatform)
{
case Device.Android:
scannerCtrl = DependencyService.Get<IBuildVersion>().Number < 21
? ((CustomCameraScanView)new CustomCameraScanView_Droid4())
: ((CustomCameraScanView)new CustomCameraScanView_Droid5());
break;
default:
scannerCtrl = new CustomCameraScanView();
break;
}
scannerCtrl.SetBinding(CustomCameraScanView.IsScanningProperty, new Binding("IsScanning", source: this.BindingContext));
scannerCtrl.SetBinding(CustomCameraScanView.IsTakingImageProperty, new Binding("IsTakingImage", source: this.BindingContext));
scannerCtrl.SetBinding(CustomCameraScanView.IsFlashlightOnProperty, new Binding("IsFlashlightOn", source: this.BindingContext));
Content = scannerCtrl;
}
}
注意: 我的第一 react 是使用隐式样式定位 CustomCameraScanView
绑定(bind)值 - 但不知何故无法让它工作。
关于xamarin - 如何在 Xamarin Forms 中的不同版本的 Android 上使用不同的自定义渲染器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44139185/