[英]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.