我想实现一种包含2个图像的“用户控件”。当我按下它时,图像源被倒置。当我释放时,图像与原始来源一起恢复。 但是,Xamarin轻拍手势不管理“按下”状态。因此,我决定将按下并释放的手势附加到各自的本地组件(Droid,iOS)。我认为自定义渲染器可以救我,但它根本不起作用:在我的Droid渲染器中,“Control”为空,所以我无法附加Touch事件。有任何想法吗 ?Xamarin Forms:具有自定义渲染器的高级ContentView组件
这里我的 “用户控制” 组件的代码:
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布局与我的表单属性。
你能给我一些细节吗?任何教程了解这部分? 我是Xamarin的初学者,我不是和android开发者。 我试图创建一个布局,其中包含两个ImageView像我的窗体,用android:id来访问它们,这要感谢FindViewById(我认为这是必要的)。 但是,如何映射imageview组件与我的DoubleImageView属性? – Klaonis
请分享你完整的解决方案,我会看看 –
我没有比我第一篇文章的内容更多的东西。 我可以添加我的布局内容,但它很荒谬。 我试图整合你的代码,但我不知道如何去做绑定android和表单数据的魔法。 – Klaonis