Aracılığıyla paylaş


Bir Görünümü Uygulama

Xamarin.Forms özel kullanıcı arabirimi denetimleri, ekrana düzenleri ve denetimleri yerleştirmek için kullanılan View sınıfından türetilmelidir. Bu makalede, cihazın kamerasındaki bir önizleme video akışını görüntülemek için kullanılan özel denetim Xamarin.Forms için özel işleyici oluşturma işlemi gösterilmektedir.

Her Xamarin.Forms görünümde, yerel denetimin bir örneğini oluşturan her platform için eşlik eden bir işleyici vardır. iOS'ta View bir Xamarin.Forms uygulama tarafından işlendiğinde, ViewRenderer sınıfı örneği oluşturulur ve bu da yerel UIView bir denetimin örneğini oluşturur. Android platformunda ViewRenderer , sınıfı yerel View bir denetim örneği oluşturur. Evrensel Windows Platformu (UWP) sınıfı ViewRenderer yerel FrameworkElement bir denetim örneği oluşturur. Eşlenmeyi denetleen Xamarin.Forms işleyici ve yerel denetim sınıfları hakkında daha fazla bilgi için bkz . oluşturucu Temel Sınıfları ve Yerel Denetimler.

Not

Android'de bazı denetimler, sınıfı kullanmayan ViewRenderer hızlı işleyiciler kullanır. Hızlı işleyiciler hakkında daha fazla bilgi için bkz Xamarin.Forms . Hızlı oluşturucular.

Aşağıdaki diyagramda, bunu uygulayan ve buna karşılık gelen yerel denetimler arasındaki View ilişki gösterilmektedir:

Görünüm Sınıfı ile Yerel Sınıfları Uygulama Arasındaki İlişki

İşleme işlemi, her platformda bir için özel işleyici oluşturarak platforma özgü özelleştirmeler uygulamak için View kullanılabilir. Bunu yapma işlemi aşağıdaki gibidir:

  1. Özel denetim Xamarin.Forms oluşturma.
  2. 'den Xamarin.Formsözel denetimi kullanma.
  3. Her platformda denetim için özel işleyici oluşturun .

Artık cihazın kamerasından bir önizleme video akışı görüntüleyen bir CameraPreview işleyici uygulamak için her öğe sırayla ele alınacaktır. Video akışına dokunulduğunda durdurulup başlatılır.

Özel Denetim Oluşturma

Aşağıdaki kod örneğinde gösterildiği gibi sınıfın alt sınıfı View oluşturularak özel bir denetim oluşturulabilir:

public class CameraPreview : View
{
  public static readonly BindableProperty CameraProperty = BindableProperty.Create (
    propertyName: "Camera",
    returnType: typeof(CameraOptions),
    declaringType: typeof(CameraPreview),
    defaultValue: CameraOptions.Rear);

  public CameraOptions Camera
  {
    get { return (CameraOptions)GetValue (CameraProperty); }
    set { SetValue (CameraProperty, value); }
  }
}

Özel CameraPreview denetim .NET Standard kitaplık projesinde oluşturulur ve denetim için API'yi tanımlar. Özel denetim, video akışının cihazdaki ön kameradan mı yoksa arka kameradan mı görüntüleneceğini denetlemek için kullanılan bir Camera özelliği kullanıma sunar. Denetim oluşturulduğunda özellik için Camera bir değer belirtilmezse, varsayılan olarak arka kamerayı belirtir.

Özel Denetimi Kullanma

Özel denetime CameraPreview konumu için bir ad alanı bildirilerek ve özel denetim öğesinde ad alanı ön eki kullanılarak .NET Standart kitaplık projesindeki XAML'de başvurulabilir. Aşağıdaki kod örneği, özel denetimin CameraPreview bir XAML sayfası tarafından nasıl tüketilebileceğini gösterir:

<ContentPage ...
             xmlns:local="clr-namespace:CustomRenderer;assembly=CustomRenderer"
             ...>
    <StackLayout>
        <Label Text="Camera Preview:" />
        <local:CameraPreview Camera="Rear"
                             HorizontalOptions="FillAndExpand"
                             VerticalOptions="FillAndExpand" />
    </StackLayout>
</ContentPage>

Ad local alanı ön eki herhangi bir adla adlandırılabilir. Ancak ve clr-namespace assembly değerleri özel denetimin ayrıntılarıyla eşleşmelidir. Ad alanı bildirildikten sonra, özel denetime başvurmak için ön ek kullanılır.

Aşağıdaki kod örneği, özel denetimin CameraPreview bir C# sayfası tarafından nasıl kullanılıp kullanılamayabileceğini gösterir:

public class MainPageCS : ContentPage
{
  public MainPageCS ()
  {
    ...
    Content = new StackLayout
    {
      Children =
      {
        new Label { Text = "Camera Preview:" },
        new CameraPreview
        {
          Camera = CameraOptions.Rear,
          HorizontalOptions = LayoutOptions.FillAndExpand,
          VerticalOptions = LayoutOptions.FillAndExpand
        }
      }
    };
  }
}

Cihazın kamerasından önizleme video akışını görüntülemek için özel denetimin bir örneği CameraPreview kullanılır. İsteğe bağlı olarak özelliği için bir değer belirtmenin Camera yanı sıra, denetimin özelleştirmesi özel işleyicide gerçekleştirilir.

Platforma özgü kamera önizleme denetimleri oluşturmak için artık her uygulama projesine özel bir işleyici eklenebilir.

Her Platformda Özel oluşturucu oluşturma

iOS ve UWP'de özel işleyici sınıfı oluşturma işlemi aşağıdaki gibidir:

  1. Özel denetimi işleyen sınıfının bir alt sınıfını ViewRenderer<T1,T2> oluşturun. İlk tür bağımsız değişkeni, işleyicinin için olduğu özel denetim olmalıdır. Bu durumda CameraPreview. İkinci tür bağımsız değişkeni, özel denetimi uygulayacak yerel denetim olmalıdır.
  2. OnElementChanged Özel denetimi işleyen yöntemini geçersiz kılın ve özelleştirmek için mantık yazın. Bu yöntem, karşılık gelen Xamarin.Forms denetim oluşturulduğunda çağrılır.
  3. Özel denetimi işlemek için kullanılacağını belirtmek için özel işleyici sınıfına Xamarin.Forms bir ExportRenderer öznitelik ekleyin. Bu öznitelik, özel işleyiciyi ile Xamarin.Formskaydetmek için kullanılır.

Android'de hızlı işleyici olarak özel işleyici sınıfı oluşturma işlemi aşağıdaki gibidir:

  1. Özel denetimi işleyen Android denetiminin bir alt sınıfını oluşturun. Ayrıca, alt sınıfın ve IViewRenderer arabirimlerini uygulayacağını IVisualElementRenderer belirtin.
  2. IVisualElementRenderer hızlı işleyici sınıfında ve IViewRenderer arabirimlerini uygulayın.
  3. Özel denetimi işlemek için kullanılacağını belirtmek için özel işleyici sınıfına Xamarin.Forms bir ExportRenderer öznitelik ekleyin. Bu öznitelik, özel işleyiciyi ile Xamarin.Formskaydetmek için kullanılır.

Not

Çoğu Xamarin.Forms öğe için, her platform projesinde özel işleyici sağlamak isteğe bağlıdır. Özel işleyici kaydedilmemişse, denetimin temel sınıfı için varsayılan işleyici kullanılır. Ancak, bir View öğesi işlenirken her platform projesinde özel işleyiciler gereklidir.

Aşağıdaki diyagramda, örnek uygulamadaki her projenin sorumlulukları ve aralarındaki ilişkiler gösterilmektedir:

CameraPreview Özel İşleyici Proje Sorumlulukları

Özel CameraPreview denetim, iOS ve UWP'de sınıfından ve Android'de sınıfından ViewRenderer türetilen platforma FrameLayout özgü işleyici sınıfları tarafından işlenir. Bu, aşağıdaki ekran görüntülerinde gösterildiği gibi her CameraPreview özel denetimin platforma özgü denetimlerle işlenmesine neden olur:

Her Platformda CameraPreview

ViewRenderer sınıfı, ilgili yerel denetimi işlemek için özel denetim oluşturulduğunda çağrılan Xamarin.Forms yöntemini kullanıma sunarOnElementChanged. Bu yöntem ve NewElement özelliklerini içeren OldElement bir ElementChangedEventArgs parametre alır. Bu özellikler, işleyicinin eklendiği öğeyi ve Xamarin.Forms sırasıyla işleyicinin eklendiği öğeyi temsil Xamarin.Forms edilir. Örnek uygulamada özelliği OldElement olur null ve NewElement özelliği örneğe bir başvuru CameraPreview içerir.

Her platforma özgü işleyici sınıfında yöntemin OnElementChanged geçersiz kılınmış bir sürümü, yerel denetim örneği oluşturma ve özelleştirme işlemlerinin gerçekleştirebileceğiniz yerdir. yöntemi SetNativeControl , yerel denetimin örneğini oluştururken kullanılmalıdır ve bu yöntem de denetim başvuruyu özelliğine Control atar. Ayrıca, işlenen denetime Xamarin.Forms bir başvuru özelliği aracılığıyla Element elde edilebilir.

Bazı durumlarda yöntemi OnElementChanged birden çok kez çağrılabilir. Bu nedenle, bellek sızıntılarını önlemek için yeni bir yerel denetim örneği oluştururken dikkatli olunmalıdır. Özel işleyicide yeni bir yerel denetimin örneğini oluştururken kullanılacak yaklaşım aşağıdaki kod örneğinde gösterilmiştir:

protected override void OnElementChanged (ElementChangedEventArgs<NativeListView> e)
{
  base.OnElementChanged (e);

  if (e.OldElement != null)
  {
    // Unsubscribe from event handlers and cleanup any resources
  }

  if (e.NewElement != null)
  {    
    if (Control == null)
    {
      // Instantiate the native control and assign it to the Control property with
      // the SetNativeControl method
    }
    // Configure the control and subscribe to event handlers
  }
}

Özelliği olduğunda Control null, yeni bir yerel denetim yalnızca bir kez örneklenmelidir. Buna ek olarak, denetim yalnızca özel işleyici yeni Xamarin.Forms bir öğeye eklendiğinde abone olunan olay işleyicileri oluşturulmalıdır. Benzer şekilde, abone olunan tüm olay işleyicileri yalnızca işleyicinin eklendiği öğe değiştiğinde aboneliği kaldırılmalıdır. Bu yaklaşımın benimsenmesi, bellek sızıntılarından muzdarip olmayan yüksek performanslı bir özel işleyici oluşturmaya yardımcı olur.

Önemli

SetNativeControl yöntemi yalnızca değilse e.NewElement nullçağrılmalıdır.

Her özel işleyici sınıfı, işleyiciyi ile kaydeden bir ExportRenderer öznitelikle Xamarin.Formsdekore edilmiştir. özniteliği iki parametre alır: işlenen özel denetimin Xamarin.Forms tür adı ve özel işleyicinin tür adı. assembly özniteliğinin ön eki, özniteliğin tüm derleme için geçerli olduğunu belirtir.

Aşağıdaki bölümlerde platforma özgü özel işleyici sınıflarının uygulanması açıklanmıştır.

iOS'ta Özel oluşturucu oluşturma

Aşağıdaki kod örneği, iOS platformu için özel işleyiciyi gösterir:

[assembly: ExportRenderer (typeof(CameraPreview), typeof(CameraPreviewRenderer))]
namespace CustomRenderer.iOS
{
    public class CameraPreviewRenderer : ViewRenderer<CameraPreview, UICameraPreview>
    {
        UICameraPreview uiCameraPreview;

        protected override void OnElementChanged (ElementChangedEventArgs<CameraPreview> e)
        {
            base.OnElementChanged (e);

            if (e.OldElement != null) {
                // Unsubscribe
                uiCameraPreview.Tapped -= OnCameraPreviewTapped;
            }
            if (e.NewElement != null) {
                if (Control == null) {
                  uiCameraPreview = new UICameraPreview (e.NewElement.Camera);
                  SetNativeControl (uiCameraPreview);
                }
                // Subscribe
                uiCameraPreview.Tapped += OnCameraPreviewTapped;
            }
        }

        void OnCameraPreviewTapped (object sender, EventArgs e)
        {
            if (uiCameraPreview.IsPreviewing) {
                uiCameraPreview.CaptureSession.StopRunning ();
                uiCameraPreview.IsPreviewing = false;
            } else {
                uiCameraPreview.CaptureSession.StartRunning ();
                uiCameraPreview.IsPreviewing = true;
            }
        }
        ...
    }
}

özelliği olması koşuluyla Control SetNativeControl, yeni UICameraPreview bir denetimin örneğini oluşturmak ve özelliğine bir başvuru atamak için yöntemi çağrılırControl.null Denetim UICameraPreview , kameradan önizleme akışını sağlamak için API'leri kullanan AVCapture platforma özgü özel bir denetimdir. Dokunulduğunda video önizlemesini OnCameraPreviewTapped durdurmak ve başlatmak için yöntemi tarafından işlenen bir Tapped olayı kullanıma sunar. Özel Tapped işleyici yeni Xamarin.Forms bir öğeye eklendiğinde ve yalnızca işleyici öğe değişikliklere eklendiğinde aboneliği kaldırıldığında olayına abone olur.

Android'de Özel oluşturucu oluşturma

Aşağıdaki kod örneği, Android platformu için hızlı işleyiciyi gösterir:

[assembly: ExportRenderer(typeof(CustomRenderer.CameraPreview), typeof(CameraPreviewRenderer))]
namespace CustomRenderer.Droid
{
    public class CameraPreviewRenderer : FrameLayout, IVisualElementRenderer, IViewRenderer
    {
        // ...
        CameraPreview element;
        VisualElementTracker visualElementTracker;
        VisualElementRenderer visualElementRenderer;
        FragmentManager fragmentManager;
        CameraFragment cameraFragment;

        FragmentManager FragmentManager => fragmentManager ??= Context.GetFragmentManager();

        public event EventHandler<VisualElementChangedEventArgs> ElementChanged;
        public event EventHandler<PropertyChangedEventArgs> ElementPropertyChanged;

        CameraPreview Element
        {
            get => element;
            set
            {
                if (element == value)
                {
                    return;
                }

                var oldElement = element;
                element = value;
                OnElementChanged(new ElementChangedEventArgs<CameraPreview>(oldElement, element));
            }
        }

        public CameraPreviewRenderer(Context context) : base(context)
        {
            visualElementRenderer = new VisualElementRenderer(this);
        }

        void OnElementChanged(ElementChangedEventArgs<CameraPreview> e)
        {
            CameraFragment newFragment = null;

            if (e.OldElement != null)
            {
                e.OldElement.PropertyChanged -= OnElementPropertyChanged;
                cameraFragment.Dispose();
            }
            if (e.NewElement != null)
            {
                this.EnsureId();

                e.NewElement.PropertyChanged += OnElementPropertyChanged;

                ElevationHelper.SetElevation(this, e.NewElement);
                newFragment = new CameraFragment { Element = element };
            }

            FragmentManager.BeginTransaction()
                .Replace(Id, cameraFragment = newFragment, "camera")
                .Commit();
            ElementChanged?.Invoke(this, new VisualElementChangedEventArgs(e.OldElement, e.NewElement));
        }

        async void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            ElementPropertyChanged?.Invoke(this, e);

            switch (e.PropertyName)
            {
                case "Width":
                    await cameraFragment.RetrieveCameraDevice();
                    break;
            }
        }       
        // ...
    }
}

Bu örnekte yöntemi, OnElementChanged özel işleyicinin yeni Xamarin.Forms bir CameraFragment öğeye eklenmesi koşuluyla bir nesne oluşturur. Türü CameraFragment , kameradan önizleme akışını sağlamak için API'yi kullanan Camera2 özel bir sınıftır. CameraFragment nesnesi, işleyici öğe değişikliklere eklendiğinde Xamarin.Forms atılır.

UWP üzerinde Özel oluşturucu oluşturma

Aşağıdaki kod örneği, UWP için özel işleyiciyi gösterir:

[assembly: ExportRenderer(typeof(CameraPreview), typeof(CameraPreviewRenderer))]
namespace CustomRenderer.UWP
{
    public class CameraPreviewRenderer : ViewRenderer<CameraPreview, Windows.UI.Xaml.Controls.CaptureElement>
    {
        ...
        CaptureElement _captureElement;
        bool _isPreviewing;

        protected override void OnElementChanged(ElementChangedEventArgs<CameraPreview> e)
        {
            base.OnElementChanged(e);

            if (e.OldElement != null)
            {
                // Unsubscribe
                Tapped -= OnCameraPreviewTapped;
                ...
            }
            if (e.NewElement != null)
            {
                if (Control == null)
                {
                  ...
                  _captureElement = new CaptureElement();
                  _captureElement.Stretch = Stretch.UniformToFill;

                  SetupCamera();
                  SetNativeControl(_captureElement);
                }
                // Subscribe
                Tapped += OnCameraPreviewTapped;
            }
        }

        async void OnCameraPreviewTapped(object sender, TappedRoutedEventArgs e)
        {
            if (_isPreviewing)
            {
                await StopPreviewAsync();
            }
            else
            {
                await StartPreviewAsync();
            }
        }
        ...
    }
}

özelliği olması koşuluyla Control yeni CaptureElement bir örnek oluşturulur ve SetupCamera kameradan önizleme akışını sağlamak için API'yi kullanan MediaCapture yöntemi nullçağrılır. Daha SetNativeControl sonra özelliğine örneğe bir başvuru atamak için CaptureElement yöntemi çağrılır Control . Denetim, CaptureElement dokunulduğunda video önizlemesini OnCameraPreviewTapped durdurmak ve başlatmak için yöntemi tarafından işlenen bir Tapped olayı kullanıma sunar. Özel Tapped işleyici yeni Xamarin.Forms bir öğeye eklendiğinde ve yalnızca işleyici öğe değişikliklere eklendiğinde aboneliği kaldırıldığında olayına abone olur.

Not

UWP uygulamasında kameraya erişim sağlayan nesneleri durdurmak ve atmak önemlidir. Bunun yapılmaması, cihazın kamerasına erişmeye çalışan diğer uygulamaları etkileyebilir. Daha fazla bilgi için bkz . Kamera önizlemesini görüntüleme.

Özet

Bu makalede, cihazın kamerasındaki bir önizleme video akışını görüntülemek için kullanılan özel denetim Xamarin.Forms için özel işleyici oluşturma işlemi gösterilmiştir. Xamarin.Forms özel kullanıcı arabirimi denetimleri, düzenleri ve denetimleri ekrana yerleştirmek için kullanılan sınıfından türetilmelidir View .