【问题标题】:How to flip Camera used by ZXing in Xamaring Forms如何在 Xamarin Forms 中翻转 ZXing 使用的相机
【发布时间】:2020-02-18 14:32:06
【问题描述】:

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

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

按钮可以在下图的右上角看到,而扫描仪视图仅在扫描打开时可见,它不在图像上。

Image of the Page where Scannning is happening

单击按钮应在使用前置和后置摄像头之间切换,前置摄像头为默认设置。但是,单击该按钮似乎没有做任何事情,然后写入我的日志。按钮的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,同时使用更改的选项重新开始扫描,但这只会导致相机冻结。

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

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

【问题讨论】:

    标签: c# xamarin xamarin.forms zxing zxing.net


    【解决方案1】:

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

    • 为此,我首先从包含它的堆栈中删除 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 值的方法是上面问题中显示的方法。

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

    【讨论】:

      【解决方案2】:

      我认为Zxing开始扫描时不能切换前后摄像头,所以必须预先选择和设置选项

       var options = new MobileBarcodeScanningOptions
       {
           AutoRotate = true,
           UseNativeScanning = true,
           TryHarder = true,
           TryInverted = true,
           UseFrontCameraIfAvailable  = true
       };
      
       var scannedCode = await _scanner.Scan(options);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-03-08
        • 1970-01-01
        • 1970-01-01
        • 2014-09-13
        相关资源
        最近更新 更多