(我最初在Xamarin论坛上发布了这个,但后来我决定在这里得到更快的答案?) TL; DR:有些布局会计算透明背景上的点按,其他布局会赢。在容器上设置InputTransparent为其所有子项设置它,我觉得孩子应该能够覆盖父项。我需要创建覆盖另一个元素的元素,并通过透明区域传递水龙头,但仍然有可点击的按钮。当我尝试使用网格时,它不起作用。我不想回到AbsoluteLayouts。我现在主要在iOS工作,我还不确定它是不是Android的问题。 Windows Phone / UWP不在桌面上。
更长的版本:
我重写了一些在较旧的Xamarin Forms(我认为1.3)中运行正常的布局。我们最近升级到2.1,它对布局代码的糟糕决定造成了严重破坏。我的任务是更新布局以表现自己。虽然我认识2.2已经发布,但我只是尝试升级,我打字的所有内容在该版本中也是如此,所以它不是2.1和2.2的问题,或者至少如果有一些改进是让他们没有帮助我。
它是一个地图应用程序,因此所有布局的核心都是昂贵的,气质不稳的OpenGL元素。这个元素非常不喜欢被重新定义,所以我采用了这种想象的XAML布局:
<ContentPage>
<CustomLayout>
<OurHeaderControl />
<TheMapControl />
<OurFooterControl />
<MapOverlay />
</CustomLayout>
</ContentPage
&#34; MapOverlay&#34;的目的是通过在页眉/页脚区域和/或地图上添加Xamarin元素来实现我们的工作流程。例如,一个布局会在页脚上方的底部添加一个方向列表,因此它显示的地图空间较小。自定义布局理解这一点并在叠加后布置地图,以便它可以请求正确的地图边界。
在这种布局中,我无法点击MapOverlay结束的任何内容。我可以把它变成InputTransparent并点击那些东西,但是它的所有子节点也都是不可点击的。在旧的布局中并非如此。
这是我在旧版面和新版面之间看到的唯一区别:
旧的布局是AbsoluteLayouts的一个复杂的混乱。它看起来像这样,我没有写出来:
<ContentPage>
<AbsoluteLayout> // "main layout"
<AbsoluteLayout> // "map layout"
<Map /> // An AbsoluteLayout containing the OpenGL view.
</AbsoluteLayout>
<AbsoluteLayout> // "child layout"
<SubPage /> // An AbsoluteLayout
</AbsoluteLayout>
</AbsoluteLayout>
</ContentPage>
主布局包含AbsoluteLayouts以约束子视图。一个子视图本身就是一个AbsoluteLayout,它包含Map和一些与之关联的其他元素。另一个子项是叠加层,它始终是一个AbsoluteLayout,其中包含与该叠加层相关的元素。这些布局都以周期相互引用,并在布局事件发生变化时相互更新。这是一个迷人的乒乓球,最终落户。通常。有时候事情就会消失。显然,这是我重写它的原因。
但是我可以点击我需要在每一层点击的内容,但我不能理解。
所以,让我们谈谈我需要做些什么,也许要弄清楚它是否是一个错误,为什么它不能正常工作,或者它是否与它一起工作是巧合其他布局。这是一个非XAML页面布局,我的项目源于您无法在共享库中使用XAML的日子:
我需要能够点击此UI中的两个按钮并让它们做出响应。
public class MyPage : ContentPage {
public MyPage() {
var mainLayout = new AbsoluteLayout();
// Two buttons will be overlaid.
var overlaidButton = new Button() {
Text = "Overlaid",
Command = new Command((o) => DisplayAlert("Upper!", "Overlaid button.", "Ah."))
};
mainLayout.Children.Add(overlaidButton, new Rectangle(0.25, 0.25, AbsoluteLayout.AutoSize, AbsoluteLayout.AutoSize), AbsoluteLayoutFlags.PositionProportional);
// The top overlay layout will be a grid.
var overlay = new Grid() {
RowDefinitions = { new RowDefinition() { Height = new GridLength(1.0, GridUnitType.Star) } },
ColumnDefinitions = {
new ColumnDefinition() { Width = new GridLength(1.0, GridUnitType.Star) },
new ColumnDefinition() { Width = new GridLength(1.0, GridUnitType.Star) },
},
BackgroundColor = Color.Transparent
};
var overlayingButton = new Button() {
Text = "Overlaying",
Command = new Command((o) => DisplayAlert("Upper!", "Overlaying button.", "Ah."))
};
overlay.Children.Add(overlayingButton, 0, 1);
mainLayout.Children.Add(overlay, new Rectangle(0, 0, 1.0, 1.0), AbsoluteLayoutFlags.All);
// This pair of property sets makes the overlaid button clickable, but not the overlaying!
// overlay.InputTransparent = true;
// upperOverlayButton.InputTransparent = false;
Content = mainLayout;
}
}
这只能让我点击&#34;覆盖&#34;即使我将网格更改为AbsoluteLayout也是按钮。
我很难过。我花了两周的时间来调试初始布局并提出了一个新的解决方案。我真的不想拆解所有的布局,并将所有内容放在一个大的AbsoluteLayout或自定义布局中。在WPF中,有两种透明:&#34;透明背景&#34;意味着背景仍然可以进行测试,并且&#34; null背景&#34;意味着背景不会受到考验。有没有办法在Xamarin中叠加这样的布局?
或者,更合适的是,为什么我们旧布局中的众多AbsoluteLayouts的复杂嵌套像我需要的那样工作,但这个更简单的布局不是?
更新
以下是我记得的一些其他信息:
答案 0 :(得分:4)
一般来说,似乎与其他两个平台相比,InputTransparent
中Grid
处理CustomGrid
的方式与iOS有关。我不是特别肯定我现在是否将当前的行为量化为一个错误,但我理解在平台行为上遇到差异是令人沮丧的。
如果我正确理解你的情况,你的情况会有各种各样的解决方法。看起来类似于之前提交的类似报告,并且通过this SO link提到了有关iOS的行为。问题出现在非Forms iOS应用程序的范围内,但逻辑可以在这里应用。
通过使用自定义渲染器(让我们使用Grid
作为示例),您可以专门实现public class CustomGrid : Grid
{
public CustomGrid() { }
}
的iOS实现,以遵循上述链接查找底层视图的方式:
CustomGrid.cs(PCL):
[assembly: ExportRenderer(typeof(CustomGrid), typeof(CustomGridRenderer))]
public class CustomGridRenderer : ViewRenderer
{
public override UIKit.UIView HitTest(CoreGraphics.CGPoint point, UIKit.UIEvent uievent)
{
UIView hitView = base.HitTest(point, uievent);
if (hitView == this)
{
return null;
}
return hitView;
}
}
CustomGrid.cs(iOS):
InputTransparent
通过这种方式,您不应为iOS明确设置InputTransparent
,并且网格上的任何点击都会发送到以下任何内容。但是,由于Android与Device.OnPlatform
一起使用,在这种特殊情况下,您可以将其包含在Device.OnPlatform(Android: () =>
{
overlay.InputTransparent = true
});
语句中,如果您不想,则跳过实现Android自定义渲染器:
CustomGrid
使用上面的代码修改后使用success function
和iOS渲染器,我可以点按两个按钮。