0

作为我正在开发的应用程序的一部分,我希望能够在使用前置摄像头或后置摄像头之间进行切换,但从我的搜索和尝试中,我无法让它使用前置摄像头工作。

进行扫描的扫描仪视图是来自 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 };
...
}

我的扫描仪将使用的选项始终在这两者之间进行选择,具体取决于设置中的一些用户输入。

试图让它工作我也试图......

  1. 在扫描运行时反转值 UseFrontCameraIfAvailable

  2. 反转用于开始扫描然后重新启动扫描的选项的值 UseFrontCameraIfAvailable - 上面显示的代码。

  3. 将 ZXingScannerView 的 IsScanning 从 true 更改为 false,同时使用更改的选项重新开始扫描,但这只会导致相机冻结。

在我即将提交问题时发现了这个我明天将尝试关注那个,但仍然非常喜欢我的输入。

如果我遗漏了一些您认为可以提供帮助的内容,请随意提出问题或要求提供其他代码。

4

2 回答 2

2

我设法弄清楚如何成功翻转相机。

  • 为此,我首先从包含它的堆栈中删除 ZXingScannerView。

  • 然后我创建 ZXingScannerView 的一个新实例,从旧实例中复制所有设置(布局定位、ZXingScannerView 特定值等)。

  • 然后我将 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 值的方法是上面问题中显示的方法。

希望这最终能帮助其他可能偶然发现同样问题的人。

于 2020-02-19T09:10:24.360 回答
1

我觉得Zxing开始扫描的时候是不能切换前后摄像头的,所以这个选项必须提前选择和设置

 var options = new MobileBarcodeScanningOptions
 {
     AutoRotate = true,
     UseNativeScanning = true,
     TryHarder = true,
     TryInverted = true,
     UseFrontCameraIfAvailable  = true
 };

 var scannedCode = await _scanner.Scan(options);
于 2020-02-19T02:13:00.867 回答