【发布时间】:2017-08-21 20:06:06
【问题描述】:
(我最初在 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
“MapOverlay”的目的是通过在页眉/页脚区域和/或地图顶部添加 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;
}
}
即使我将 Grid 更改为 AbsoluteLayout,这也只能让我点击“叠加”按钮。
我被难住了。我花了 2 周时间来调试初始布局并提出新的解决方案。我真的不想拆散我们所有的布局并将所有内容放在一个大的 AbsoluteLayout 或自定义布局中。在WPF中,有两种透明:“背景透明”表示背景仍然可以命中测试,“空背景”表示背景不能命中测试。有没有办法像这样在 Xamarin 中覆盖布局?
或者,更恰当地说,为什么我们的旧布局中众多 AbsoluteLayouts 的复杂嵌套可以像我需要的那样工作,但这个更简单的布局却不是?
更新
以下是我记得的一些附加信息:
- 此行为特定于 iOS。在 Android 上,示例代码和我们的代码都可以工作。
- 我不是第一个遇到这个问题的人:On StackOverflow.On Xamarin's Forums.
【问题讨论】:
标签: xamarin.forms