簡體   English   中英

Xamarin Forms:具有自定義渲染器的高級ContentView組件

[英]Xamarin Forms : advanced ContentView component with custom renderer

我想實現一種包含2個圖像的“用戶控件”。 當我按它時,圖像源被反轉。 當我發布時,圖像將使用原始來源還原。 但是,Xamarin輕擊手勢無法管理“按下”狀態。 因此,我決定將按下和釋放的手勢附加到各自的本機組件(Droid,iOS)中。 我以為自定義渲染器可以救我,但是根本不起作用:在我的Droid渲染器中,“控件”為null,因此我無法附加Touch事件。 有任何想法嗎 ?

這是我的“用戶控件”組件的代碼:

XAML

<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Xam_Test.Views.DoubleImageView">
    <ContentView.Content>
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>

            <Image Source="{Binding FirstImageSource}" Aspect="AspectFit" HeightRequest="{Binding ImageSize}"/>

            <Image Grid.Column="1" Margin="10,0,0,0" Source="{Binding SecondImageSource}" Aspect="AspectFit" HeightRequest="{Binding ImageSize}"/>
        </Grid>
    </ContentView.Content>
</ContentView>

背后的代碼

public partial class DoubleImageView : ContentView
    {
        public static readonly BindableProperty FirstImageSourceProperty = BindableProperty.Create("FirstImageSource", typeof(string), typeof(DoubleImageView), string.Empty);
        public string FirstImageSource
        {
            set { SetValue(FirstImageSourceProperty, value); }
            get { return (string)GetValue(FirstImageSourceProperty); }
        }


        public static readonly BindableProperty ImageSizeProperty = BindableProperty.Create("ImageSize", typeof(int), typeof(DoubleImageView), 44);
        public int ImageSize
        {
            set { SetValue(ImageSizeProperty, value); }
            get { return (int)GetValue(ImageSizeProperty); }
        }


        public static readonly BindableProperty SecondImageSourceProperty = BindableProperty.Create("SecondImageSource", typeof(string), typeof(DoubleImageView), string.Empty);
        public string SecondImageSource
        {
            set { SetValue(SecondImageSourceProperty, value); }
            get { return (string)GetValue(SecondImageSourceProperty); }
        }


        public ICommand SwitchImageCommand { get; set; }

        public DoubleImageView()
        {
            BindingContext = this;
            SwitchImageCommand = new Command<bool>((bool isPressed) => UpdateImages(isPressed));
            InitializeComponent();
        }

        private void UpdateImages(bool isPressed)
        {
            string source;
            if (isPressed)
            {
                source = SecondImageSource;
                SecondImageSource = FirstImageSource;
                FirstImageSource = source;
            }
            else
            {
                source = FirstImageSource;
                FirstImageSource = SecondImageSource;
                SecondImageSource = source;
            }
        }
    }

這是我的Droid渲染器

[assembly: ExportRenderer(typeof(DoubleImageView), typeof(DoubleImageViewRenderer))]
namespace YourNameSpace.Droid.Renderers
{
    class DoubleImageViewRenderer : ViewRenderer
    {
        private ICommand _updateUICommand;

        protected override void Dispose(bool disposing)
        {
            //MANAGE touch events
            if (_updateUICommand != null)
            {
                Control.Touch -= Image_Touch;
            }

            _updateUICommand = null;

            base.Dispose(disposing);
        }

        protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.View> e)
        {
            base.OnElementChanged(e);

            if (Control == null)
            {
                var view = (Context as Activity).LayoutInflater.Inflate(Resource.Layout.doubleimage, this, false);
                var firstImage = view.FindViewById<ImageView>(Resource.Id.first_imageView);
                var secondImage = view.FindViewById<ImageView>(Resource.Id.second_imageview);
                // ??????
                SetNativeControl(view);
            }

            if (Control != null)
            {
                DoubleImageView formView = (e.NewElement as DoubleImageView);

                ExtractFormData(formView);

                //MANAGE touch events
                if (_updateUICommand != null)
                {
                    Control.Touch += Image_Touch;
                }
            }
        }

        private void Image_Touch(object sender, TouchEventArgs e)
        {
            var handled = false;
            if (e.Event.Action == MotionEventActions.Down)
            {
                _updateUICommand.Execute(true);
                handled = true;
            }
            else if (e.Event.Action == MotionEventActions.Up)
            {
                _updateUICommand.Execute(false);

                handled = true;
            }

            e.Handled = handled;
        }

        /// <summary>
        /// Extract form view data
        /// </summary>
        /// <param name="formImage">form view object</param>
        private void ExtractFormData(DoubleImageView formView)
        {
            _updateUICommand = formView.SwitchImageCommand;
        }
    }
}

編輯

顯然,我必須創建一個Android布局來使用SetNativeControl管理我的自定義組件的渲染。 這是我的自定義布局。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >
  <ImageView android:id="@+id/first_imageview"/>
  <ImageView android:id="@+id/second_imageview"/>
</LinearLayout>

我不知道如何將我的android布局與表單屬性綁定在一起。

如果從ViewRenderer派生,則Control將為null。 您必須使用SetNativeControl(view)進行設置。

適用於iOS

UIView view = new UIView();
view.Add(...)
SetNativeControl(view)

對於Android,如果您有布局:

var view = (this.Context as Activity).LayoutInflater.Inflate(Resource.Layout.MyLayout, this, false);
SetNativeControl(view);

看來您需要告訴ViewRenderer它實際在渲染什么。 有默認的渲染,例如EntryRenderer和ImageRenderer。 我有一個自定義的點擊手勢渲染器,我使用的是這個...

ViewRenderer<GestureControl, Android.Widget.RelativeLayout>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM