Arhn - архитектура программирования

Как создать и внедрить Android CustomOverlay для сканера ZXing?

Я использую плагин сканера штрих-кода ZXing для своего проекта Xamarin.Forms. Согласно некоторым сообщениям, мне нужно использовать настраиваемый оверлей для сканера ZXing, чтобы была кнопка отмены. Но я не знаком с разработкой Android в проекте Xamarin.Forms.

До сих пор я знаю, что сканер (плагин MobileBarcodeScanner из ZXing) принимает Android.Views.View в качестве наложения, чтобы заменить просмотр страницы сканирования по умолчанию.

public async Task<string> ScanAsync()
{
    MobileBarcodeScanner scanner = new MobileBarcodeScanner();
    scanner.UseCustomOverlay = true;
    scanner.CustomOverlay = ???????;

    var scanResult = await scanner.Scan();
    if (scanResult != null)
    { return scanResult.Text; }
    return null;
}

Но я не знаю, как создать страницу просмотра (в XML-дизайне или программно) и установить ее на scanner.CustomOverlay.

Я не уверен, можно ли использовать обычное представление Android для сканера, любая подробная ссылка будет действительно полезна.

Спасибо.


Ответы:


1

Если вы хотите настроить наложение, вы должны создать собственное представление для каждой платформы. Вы можете настроить свой оверлей следующим образом (создайте пользовательский оверлей с именем ZxingOverlayView и установите его на scanner.CustomOverlay):

var scanner = new ZXing.MobileMobileBarcodeScanner();
scanner.UseCustomOverlay = true;
myCustomOverlayInstance = new ZxingOverlayView(this, scanner);
scanner.CustomOverlay = myCustomOverlayInstance;

ZxingOverlayView должен унаследовать view, а затем добавить ваш элемент управления в настраиваемое представление. Вы можете увидеть подробности об этой ссылке.

http://slackshotindustries.blogspot.com/2013/04/creating-custom-overlays-in-xzing.html

Изменить

Есть полностью шаги.

Прежде всего, вы можете создать интерфейс для службы зависимости.

 public interface IDeviceService
  {
    Task<string> ScanAsync();
  }

Вы можете использовать этот интерфейс в коде PCL.

  private async void DependencyButton_Clicked(object sender, EventArgs e)
    {
        var result = await DependencyService.Get<IDeviceService>().ScanAsync();
        if (!string.IsNullOrEmpty(result))
        {
            await DisplayAlert(result, null, "OK");
        }
    }

В платформе android. Вы можете разработать свой макет. Прежде всего, создайте макет

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
    android:id="@+id/imgClose"
    android:layout_width="30dp"
    android:layout_height="30dp"
    android:src="@drawable/close"
    android:layout_marginTop="20dp"
    android:layout_marginLeft="20dp"/>
  <RelativeLayout
    android:id="@+id/llScan"
    android:layout_width="240dp"
    android:layout_height="240dp"
    android:layout_centerInParent="true"
    android:background="@drawable/scan">
  <ImageView
        android:id="@+id/imgLine"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:src="@drawable/scan_line"
        android:layout_centerHorizontal="true" />
     </RelativeLayout>
  <View
    android:id="@+id/viewTop"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_above="@id/llScan"
    android:background="@color/title_black"/>
 <View
    android:id="@+id/viewBottom"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@id/llScan"
    android:background="@color/title_black"
    android:layout_alignParentBottom="true"/>
 <View
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@id/viewTop"
    android:layout_toLeftOf="@id/llScan"
    android:layout_above="@id/viewBottom"
    android:background="@color/title_black"/>
 <View
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_below="@id/viewTop"
    android:layout_above="@id/viewBottom"
    android:layout_toRightOf="@id/llScan"
    android:background="@color/title_black"/>
 </RelativeLayout>

Затем добейтесь интерфейса службы зависимости и используйте свой новый макет.

 [assembly: Xamarin.Forms.Dependency(typeof(DeviceService))]
 namespace Sample.Droid
 {
  public class DeviceService : IDeviceService
 {
    public async Task<string> ScanAsync()
    {
        var scanner = new ZXing.Mobile.MobileBarcodeScanner
        {
            UseCustomOverlay = true

        };
        //scanner.CustomOverlay = new CustomScanView(Application.Context);
        var options = new ZXing.Mobile.MobileBarcodeScanningOptions()
        {
            TryHarder = true,
            AutoRotate = false,
            UseFrontCameraIfAvailable = false,
            CameraResolutionSelector = new CameraResolutionSelectorDelegate(SelectLowestResolutionMatchingDisplayAspectRatio),
            PossibleFormats = new List<ZXing.BarcodeFormat>()
            {
                ZXing.BarcodeFormat.QR_CODE
            }
        };

        View scanView = LayoutInflater.From(Application.Context).Inflate(Resource.Layout.ScanView, null);
        ImageView imgLine = scanView.FindViewById<ImageView>(Resource.Id.imgLine);
        ImageView imgClose = scanView.FindViewById<ImageView>(Resource.Id.imgClose);
        imgClose.Click += delegate
        {
            scanner.Cancel();
        };
        scanner.CustomOverlay = scanView;

        ObjectAnimator objectAnimator = ObjectAnimator.OfFloat(imgLine, "Y", 0, DpToPixels(240));
        objectAnimator.SetDuration(2500);
        objectAnimator.RepeatCount = -1;
        objectAnimator.SetInterpolator(new LinearInterpolator());
        objectAnimator.RepeatMode = ValueAnimatorRepeatMode.Restart;
        objectAnimator.Start();

        ZXing.Result scanResults = await scanner.Scan(CrossCurrentActivity.Current.Activity, options);
        if (scanResults != null)
        {
            return scanResults.Text;
        }
        return string.Empty;
    }

    private int DpToPixels(double dp)
    {
        return (int)(dp * Application.Context.Resources.DisplayMetrics.Density);
    }

    private CameraResolution SelectLowestResolutionMatchingDisplayAspectRatio(List<CameraResolution> availableResolutions)
    {
        CameraResolution result = null;
        //a tolerance of 0.1 should not be visible to the user
        double aspectTolerance = 0.1;
        var displayOrientationHeight = DeviceDisplay.MainDisplayInfo.Orientation == DisplayOrientation.Portrait ? DeviceDisplay.MainDisplayInfo.Height : DeviceDisplay.MainDisplayInfo.Width;
        var displayOrientationWidth = DeviceDisplay.MainDisplayInfo.Orientation == DisplayOrientation.Portrait ? DeviceDisplay.MainDisplayInfo.Width : DeviceDisplay.MainDisplayInfo.Height;
        //calculatiing our targetRatio
        var targetRatio = displayOrientationHeight / displayOrientationWidth;
        var targetHeight = displayOrientationHeight;
        var minDiff = double.MaxValue;
        //camera API lists all available resolutions from highest to lowest, perfect for us
        //making use of this sorting, following code runs some comparisons to select the lowest resolution that matches the screen aspect ratio and lies within tolerance
        //selecting the lowest makes Qr detection actual faster most of the time
        foreach (var r in availableResolutions.Where(r => Math.Abs(((double)r.Width / r.Height) - targetRatio) < aspectTolerance))
        {
            //slowly going down the list to the lowest matching solution with the correct aspect ratio
            if (Math.Abs(r.Height - targetHeight) < minDiff)
                minDiff = Math.Abs(r.Height - targetHeight);
            result = r;
        }
        return result;
    }
   }

}

Код iOS.

[assembly: Xamarin.Forms.Dependency(typeof(DeviceService))]
namespace Sample.iOS
{
public class DeviceService : IDeviceService
{
    public async Task<string> ScanAsync()
    {
        var scanner = new ZXing.Mobile.MobileBarcodeScanner()
        {
            UseCustomOverlay = true
        };

        var options = new ZXing.Mobile.MobileBarcodeScanningOptions()
        {
            TryHarder = true,
            AutoRotate = false,
            UseFrontCameraIfAvailable = false,
            PossibleFormats = new List<ZXing.BarcodeFormat>()
            {
                ZXing.BarcodeFormat.QR_CODE
            }
        };

        ScannerOverlayView customOverlay = new ScannerOverlayView();
        customOverlay.OnCancel += () =>
        {
            scanner?.Cancel();
        };
        customOverlay.OnResume += () =>
        {
            scanner?.ResumeAnalysis();
        };
        customOverlay.OnPause += () =>
        {
            scanner?.PauseAnalysis();
        };
        scanner.CustomOverlay = customOverlay;


        ZXing.Result scanResults = null;
        scanResults = await scanner.Scan(options);
        //customOverlay.Dispose();
        if (scanResults != null)
        {
            return scanResults.Text;
        }
        return string.Empty;
    }
}

Вот работает GIF.

введите здесь описание изображения

Вот хороший простой код. вы могли бы сослаться на это. https://github.com/Wenfengcheng/ZXing.Sample_Xamarin

01.08.2019
  • Я прочитал эту статью до того, как создал эту ветку, но я не понял, что написано в этой статье. На данный момент я переключился на ZXing.Form и перешел на страницу сканирования, включив панель навигации с кнопкой возврата. Я не уверен, сработает ли это на iOS. Думаю, позже я подробнее рассмотрю эту статью. Спасибо за то, что поделились. 01.08.2019
  • @solidcomer Я отредактировал свой ответ, я добавил полные шаги для создания макета, вы можете обратиться к нему. В конце концов, добиться этого очень просто. 01.08.2019
  • @solidcomer В демонстрационном коде есть код достижения IOS 01.08.2019
  • Спасибо большое! Я отметил это на прошлой неделе, но забыл добавить комментарий. 08.08.2019
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..