作为我正在开发的应用程序的一部分,我希望能够在使用前置摄像头或后置摄像头之间进行切换,但从我的搜索和尝试来看,我一直无法使用前置摄像头。
执行扫描的扫描仪视图是来自ZXing.Net.Mobile.Forms的一个名为ZXingScannerView的视图,在我的xaml中这样定义,以及应该翻转相机的按钮。
<elements:AdvancedTabbedPage
...
xmlns:elements="clr-namespace:Wolf.Utility.Main.Xamarin.Elements;assembly=Wolf.Utility.Main"
xmlns:forms="clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms">
...
<ContentPage>
<ContentPage.ToolbarItems>
<ToolbarItem Text="{x:Static resources:AppResources.CameraFlipText}" x:Name="CameraFlipButton" Clicked="CameraFlipButton_OnClicked"/>
</ContentPage.ToolbarItems>
<ContentPage.Content>
...
<forms:ZXingScannerView x:Name="ScannerView" HeightRequest="200" IsAnalyzing="False" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" IsVisible="False" IsScanning="True"/>
...
</ContentPage.Content>
</ContentPage>
按钮可以在下图的右上角看到,而扫描仪视图只有在扫描打开时才可见,而扫描不在图像上。
正在进行扫描的页面的图像
单击该按钮应在使用前置摄像头和后置摄像头之间切换,前置摄像头为默认设置。然而,点击按钮似乎什么都没做,只会写入我的日志。下面可以看到按钮的Clicked事件的代码。
...
private void CameraFlipButton_OnClicked(object sender, EventArgs e)
{
Logging.Log(LogType.Information, "Flipping Camera...");
Config.DefaultOptions.UseFrontCameraIfAvailable = !Config.DefaultOptions.UseFrontCameraIfAvailable;
Config.CustomOptions.UseFrontCameraIfAvailable = !Config.CustomOptions.UseFrontCameraIfAvailable;
if (!ScanningToggle.IsToggled) return;
Logging.Log(LogType.Information, "Restarting Scanning...");
ScanningToggle.IsToggled = false;
ScanningToggle.IsToggled = true;
}
上面代码中提到的选项是这样定义的,在我的Config类中。在我的Config类的Init方法中设置了名为CustomOptions的附加值,但这些值与这个问题无关。
public class Config
{
...
public static MobileBarcodeScanningOptions CustomOptions = new MobileBarcodeScanningOptions() { UseFrontCameraIfAvailable = true };
public static MobileBarcodeScanningOptions DefaultOptions = new MobileBarcodeScanningOptions() { UseFrontCameraIfAvailable = true };
...
}
我的扫描仪将使用的选项总是在这两个选项之间选择,这取决于设置中的一些用户输入。
为了让它发挥作用,我也尝试过…
在扫描运行时反转UseFrontCameraIfAvailable值
反转用于启动扫描的选项上的值UseFrontCameraIfAvailable,然后重新启动扫描-上面显示的代码。
将ZXingScannerView的IsScanning从true更改为false,同时使用更改的选项重新启动扫描,但这只会导致相机冻结。
在我准备提交问题时发现了这个。我明天会尝试遵循这一点,但仍然非常喜欢我的意见。
可以自由提问,或者如果我遗漏了一些内容,可以要求额外的代码,你认为这会有所帮助。
我设法弄清楚如何成功翻转相机。
-
为此,我首先从包含ZXingScannerView的堆栈中删除它。
-
然后,我创建了一个ZXingScannerView的新实例,复制了旧实例中的所有设置(布局定位、ZXingScanerView特定值等(。
-
然后,我将ZXingScannerView重新添加到堆栈中,对UseFrontCameraIfAvailable属性的任何更改都将生效。
它成功编写的代码如下。首先是复制属性的通用方法,然后是重新创建ZXingScannerView的方法,最后是我的启用扫描的方法。
public class GenericFactory
{
// Assistance with Setter Accessibility: https://stackoverflow.com/questions/3762456/how-to-check-if-property-setter-is-public
public static T CopyProperties<T>(T newObject, T oldObject, bool ignoreDefaults = true,
bool skipSelectedProperties = true, params string[] skippedProperties) where T : class
{
var type = typeof(T);
var properties = type.GetProperties();
foreach (var property in properties)
{
if (ignoreDefaults && property.GetValue(oldObject) == default)
continue;
if (skipSelectedProperties && skippedProperties.Contains(property.Name))
continue;
if (!property.CanWrite)
continue;
property.SetValue(newObject, property.GetValue(oldObject));
}
return newObject;
}
}
private void RecreateScannerView()
{
if (Config.DebugMode) Logging.Log(LogType.Debug, $"{nam1eof(RecreateScannerView)} method called");
ScannerStack.Children.Remove(ScannerView);
if (Config.DebugMode)
Logging.Log(LogType.Debug,
$"Coping properties from existing {nameof(ZXingScannerView)} into a new {nameof(ZXingScannerView)}");
ScannerView = GenericFactory.CopyProperties(new ZXingScannerView() {IsScanning = false}, ScannerView,
skippedProperties: new List<string>() {nameof(ScannerView.IsScanning)}.ToArray());
ScannerView.OnScanResult += ScannerView_OnScanResult;
ScannerStack.Children.Add(ScannerView);
}
private void EnableScan(MobileBarcodeScanningOptions imputedOptions = null)
{
if (Config.DebugMode) Logging.Log(LogType.Debug, $"{nameof(EnableScan)} Method is run in Thread named => {Thread.CurrentThread.Name}");
var chosenOptions = imputedOptions ?? (Config.UseCustomOptions ? Config.CustomOptions : Config.DefaultOptions);
if (Config.DebugMode)
Logging.Log(LogType.Information,
$"Chose this option for Scanning => {(imputedOptions != null ? nameof(imputedOptions) : (Config.UseCustomOptions ? nameof(Config.CustomOptions) : nameof(Config.DefaultOptions)))}");
ScannerView.Options = chosenOptions;
RecreateScannerView();
Logging.Log(LogType.Information, $"Starting the Scanning...");
ScannerView.IsScanning = true;
ScannerView.IsAnalyzing = true;
ScannerView.IsVisible = true;
if (Config.DebugMode)
Logging.Log(LogType.Debug,
$"{nameof(EnableScan)} Called and Finished; ScannerView.IsAnalyzing => {ScannerView.IsAnalyzing}; ScannerView.IsVisible => {ScannerView.IsVisible}");
}
我翻转UseFrontCameraIfAvailable值的方法是上面问题中显示的方法。
希望这最终能帮助其他可能偶然发现类似问题的人。
我认为当它开始使用Zxing扫描时,它无法切换前后摄像头,因此必须事先选择并设置选项
var options = new MobileBarcodeScanningOptions
{
AutoRotate = true,
UseNativeScanning = true,
TryHarder = true,
TryInverted = true,
UseFrontCameraIfAvailable = true
};
var scannedCode = await _scanner.Scan(options);