我有以下Xamarin.Forms TemplatedView:
using System;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;
namespace STM.Framework.Controls
{
[ContentProperty(nameof(Content))]
public class PopOverLayout : TemplatedView
{
public PopOverLayout()
{
}
#region BoxViewTapCommand
public static BindableProperty BoxViewTapCommandProperty = BindableProperty.Create(nameof(BoxViewTapCommand), typeof(ICommand), typeof(PopOverLayout), default(ICommand), defaultValueCreator: BoxViewTapCommandCreator);
private static object BoxViewTapCommandCreator(BindableObject bindable)
{
return new Command(p => BoxViewTappedExecute(bindable as PopOverLayout, p));
}
private static void BoxViewTappedExecute(PopOverLayout bindable, object parameter)
{
bindable.IsOverlayVisible = !bindable.IsOverlayVisible;
if (!bindable.IsOverlayVisible)
{
bindable.OverlayContent.InputTransparent = true;
}
}
public ICommand BoxViewTapCommand
{
get { return (ICommand) GetValue(BoxViewTapCommandProperty); }
set { SetValue(BoxViewTapCommandProperty, value); }
}
#endregion BoxViewTapCommand
#region OverlayContent
public static BindableProperty OverlayContentProperty = BindableProperty.Create(nameof(OverlayContent), typeof(VisualElement), typeof(PopOverLayout), default(VisualElement));
public VisualElement OverlayContent
{
get { return (VisualElement) GetValue(OverlayContentProperty); }
set { SetValue(OverlayContentProperty, value); }
}
#endregion OverlayContent
#region Content
public static BindableProperty ContentProperty = BindableProperty.Create(nameof(Content), typeof(VisualElement), typeof(PopOverLayout), default(VisualElement));
public VisualElement Content
{
get { return (VisualElement) GetValue(ContentProperty); }
set { SetValue(ContentProperty, value); }
}
#endregion Content
#region IsOverlayVisible
public static BindableProperty IsOverlayVisibleProperty = BindableProperty.Create(nameof(IsOverlayVisible), typeof(bool), typeof(PopOverLayout), default(bool));
public bool IsOverlayVisible
{
get { return (bool) GetValue(IsOverlayVisibleProperty); }
set { SetValue(IsOverlayVisibleProperty, value); }
}
#endregion IsOverlayVisible
}
}
的App.xaml:
<Style TargetType="{x:Type controls:PopOverLayout}">
<Setter Property="BackgroundColor" Value="#88000000" />
<Setter Property="IsOverlayVisible" Value="False" />
<Setter Property="ControlTemplate">
<Setter.Value>
<ControlTemplate>
<Grid BackgroundColor="{TemplateBinding BackgroundColor}" >
<Grid.RowDefinitions>
<RowDefinition>
<RowDefinition.Height>
<OnIdiom x:TypeArguments="GridLength" Phone="0" Tablet="50" />
</RowDefinition.Height>
</RowDefinition>
<RowDefinition Height="*" />
<RowDefinition>
<RowDefinition.Height>
<OnIdiom x:TypeArguments="GridLength" Phone="0" Tablet="50" />
</RowDefinition.Height>
</RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition>
<ColumnDefinition.Width>
<OnIdiom x:TypeArguments="GridLength" Phone="0" Tablet="50" />
</ColumnDefinition.Width>
</ColumnDefinition>
<ColumnDefinition Width="*" />
<ColumnDefinition>
<ColumnDefinition.Width>
<OnIdiom x:TypeArguments="GridLength" Phone="0" Tablet="50" />
</ColumnDefinition.Width>
</ColumnDefinition>
</Grid.ColumnDefinitions>
<controls:EnhancedContentPresenter Grid.Row="0" Grid.Column="0" Grid.RowSpan="3" Grid.ColumnSpan="3"
Content="{TemplateBinding Content}" />
<BoxView Grid.Row="0" Grid.Column="0" Grid.RowSpan="3" Grid.ColumnSpan="3"
InputTransparent="{TemplateBinding IsOverlayVisible, Converter={StaticResource BooleanInversionConverter}, Mode=OneWay}"
IsVisible="{TemplateBinding IsOverlayVisible}"
BackgroundColor="{TemplateBinding BackgroundColor}">
<BoxView.GestureRecognizers>
<TapGestureRecognizer Command="{TemplateBinding BoxViewTapCommand}"></TapGestureRecognizer>
</BoxView.GestureRecognizers>
</BoxView>
<controls:EnhancedContentPresenter Grid.Row="1" Grid.Column="1" Content="{TemplateBinding OverlayContent}"
InputTransparent="{TemplateBinding IsOverlayVisible, Converter={StaticResource BooleanInversionConverter}, Mode=OneWay}"
IsVisible="{TemplateBinding IsOverlayVisible}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
转换器:
public class BooleanInversionConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (targetType != typeof(bool))
throw new NotSupportedException();
if (value.GetType() != typeof(bool))
throw new NotSupportedException();
var casted = (bool)value;
return !casted;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
if (targetType != typeof(bool))
throw new NotSupportedException();
if (value.GetType() != typeof(bool))
throw new NotSupportedException();
var casted = (bool)value;
return !casted;
}
}
ContentPresenter:
public class EnhancedContentPresenter : ContentPresenter
{
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
if (BindingContext != null && this.Content != null)
SetInheritedBindingContext(this.Content, BindingContext);
}
}
由于控件的性质,很明显我想要做的事情我想:如果隐藏叠加层我不希望叠加层捕获点击(或其他)事件,而是表现得像它甚至不存在。
然而,我似乎无法使其正常工作,因为即使隐藏了叠加并且InputTransparent设置为true,某些东西仍会捕捉触摸事件。
这个问题对任何人都响了吗?
答案 0 :(得分:0)
我不确定templatedView是否仍有问题(因为他们肯定缺少很多wpf功能),但这样做的效果很好:
[ContentProperty(nameof(Content))]
public class PopOverLayout : RelativeLayout
{
#region OverlayContent
public static BindableProperty OverlayContentProperty = BindableProperty.Create(nameof(OverlayContent), typeof(View), typeof(PopOverLayout), default(View), propertyChanged: OverlayContentChanged);
private static void OverlayContentChanged(BindableObject bindable, object oldValue, object newValue)
{
var layout = bindable as PopOverLayout;
if (layout == null)
return;
layout.UpdateOverlayContent();
}
public View OverlayContent
{
get { return (View) GetValue(OverlayContentProperty); }
set { SetValue(OverlayContentProperty, value); }
}
#endregion OverlayContent
#region Content
public static BindableProperty ContentProperty = BindableProperty.Create(nameof(Content), typeof(View), typeof(PopOverLayout), default(View), propertyChanged: ContentChanged);
private static void ContentChanged(BindableObject bindable, object oldvalue, object newvalue)
{
var layout = bindable as PopOverLayout;
if (layout == null)
return;
layout.UpdateDisplayContent();
}
public View Content
{
get { return (View) GetValue(ContentProperty); }
set { SetValue(ContentProperty, value); }
}
#endregion Content
#region IsOverlayVisible
public static BindableProperty IsOverlayVisibleProperty = BindableProperty.Create(nameof(IsOverlayVisible), typeof(bool), typeof(PopOverLayout), default(bool), propertyChanged: IsOverlayVisibleChanged);
private static void IsOverlayVisibleChanged(BindableObject bindable, object oldvalue, object newvalue)
{
var layout = bindable as PopOverLayout;
if (layout == null)
return;
bool newState = (bool) newvalue;
if (newState)
{
layout.ShowPopup();
}
else
{
layout.HidePopup();
}
}
public bool IsOverlayVisible
{
get { return (bool) GetValue(IsOverlayVisibleProperty); }
set { SetValue(IsOverlayVisibleProperty, value); }
}
#endregion IsOverlayVisible
protected override void OnParentSet()
{
base.OnParentSet();
UpdateDisplayContent();
UpdateOverlayContent();
}
private View content;
private RelativeLayout popup;
private void UpdateDisplayContent()
{
if (content != null)
this.Children.Remove(content);
if (Content != null)
{
content = Content;
this.Children.Add(content,
Constraint.Constant(0),
Constraint.Constant(0),
Constraint.RelativeToParent(layout => layout.Width),
Constraint.RelativeToParent(layout => layout.Height));
Content.InputTransparent = IsOverlayVisible;
}
}
private void UpdateOverlayContent()
{
if (popup != null)
this.Children.Remove(popup);
if (OverlayContent != null && IsOverlayVisible)
{
ShowPopup();
}
}
private void HidePopup()
{
if (popup != null)
this.Children.Remove(popup);
OverlayContent.InputTransparent = true;
Content.InputTransparent = false;
}
private void ShowPopup()
{
if (popup != null)
this.Children.Remove(popup);
popup = new RelativeLayout();
popup.GestureRecognizers.Add(new TapGestureRecognizer() {Command = new Command(PopUpTapped)});
popup.BackgroundColor = BackgroundColor;
this.Children.Add(popup,
Constraint.Constant(0),
Constraint.Constant(0),
Constraint.RelativeToParent(layout => layout.Width),
Constraint.RelativeToParent(layout => layout.Height));
popup.Children.Add(OverlayContent,
Constraint.RelativeToParent(layout => layout.X + 20),
Constraint.RelativeToParent(layout => layout.Y + 20),
Constraint.RelativeToParent(layout => layout.Width - 40),
Constraint.RelativeToParent(layout => layout.Height - 40));
OverlayContent.InputTransparent = false;
Content.InputTransparent = true;
}
private void PopUpTapped(object o)
{
this.IsOverlayVisible = !IsOverlayVisible;
}
}