如何覆盖两个Xamarin Forms布局,以便它们都可以接收触摸输入? [英] How do I overlay two Xamarin Forms layouts such that both can receive touch inputs?

查看:53
本文介绍了如何覆盖两个Xamarin Forms布局,以便它们都可以接收触摸输入?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(我最初在Xamarin论坛上发布了此内容,但后来决定我可能会在这里得到更快的答案?) TL; DR:某些布局会在透明背景上计算点击次数,而其他布局则不会.在容器上设置InputTransparent会为其所有子级设置它,我觉得子级应该能够覆盖父级.我需要创建覆盖另一个元素的元素,并使水龙头穿过透明区域,但仍然具有可轻按的按钮.当我尝试使用Grid时,它不起作用.我不想回到AbsoluteLayouts.我现在主要在iOS上工作,我不确定在Android中是否有问题.桌上没有Windows Phone/UWP.

(I posted this initially on the Xamarin Forums, but then decided I might get a faster answer here?) TL;DR: Some layouts will count a tap on a transparent background, others won't. Setting InputTransparent on a container sets it for all of its children, and I feel like children should be able to override the parent. I need to create elements that overlay another element and pass taps through a transparent region but still have tappable buttons. When I try this with a Grid, it doesn't work. I don't want to go back to AbsoluteLayouts. I'm mostly working in iOS right now, I'm not quite sure if it's a problem in Android yet. Windows Phone/UWP isn't on the table.

长版:

我正在重写一些在较旧的Xamarin Forms(我认为1.3)中可以正常使用的布局.我们最近升级到2.1,它严重破坏了布局代码的错误决定.我的任务是更新布局以表现自己.虽然我认识到2.2已经发布,但我只是尝试了一次升级,并且我键入的所有内容在该版本中也都正确,因此,这不是2.1与2.2的问题,或者至少是进行了一些改进后,它们还是无济于事我.

I'm rewriting some layouts that worked OK in an older Xamarin Forms (1.3 I think). We recently upgraded to 2.1, and it wreaked havoc on the layout code's bad decisions. I'm tasked with updating the layouts to behave themselves. While I recognize 2.2 has been released, I just tried an upgrade and everything I'm typing seems true in that version as well, so it's not a 2.1 vs. 2.2 issue, or at least if some improvements are made they aren't helping me.

这是一个贴图应用程序,因此所有布局的核心都是昂贵的,气质的OpenGL元素.这个元素非常不希望被重新创建,因此我采用了一种类似于这种虚构XAML的布局:

It's a mapping application, so the centerpiece of all layouts is an expensive, temperamental OpenGL element. This element very much does not like to be reparented, so I've adopted a layout sort of like this imaginary XAML:

<ContentPage>
    <CustomLayout>
        <OurHeaderControl /> 
        <TheMapControl /> 
        <OurFooterControl /> 
        <MapOverlay /> 
    </CustomLayout>
</ContentPage

"MapOverlay"的目的是通过在页眉/页脚区域和/或地图的顶部添加Xamarin元素来实现我们的工作流程.例如,一种布局在页脚上方的底部添加了一个方向列表,因此地图的显示空间较小.自定义布局可以理解这一点,并在覆盖后布置地图,以便它可以请求正确的地图边界.

The purpose of "MapOverlay" is to implement our workflows by adding Xamarin elements on top of the header/footer areas and/or the map. For example, one layout adds a list of directions to the bottom above the footer, so it has less room for the map to appear. The custom layout understands this and lays out the map after the overlay so it can ask for the correct map bounds.

在此布局中,我无法点击MapOverlay上方的任何内容.我可以将其设置为InputTransparent并点击这些内容,但是它的所有子级也都无法被点击.在旧版式中并非如此.

In this layout, I cannot tap on anything the MapOverlay is over. I can make it InputTransparent and tap those things, but then all of its children are also not tappable. This was not true in the old layouts.

这是我看到的旧版和新版之间的唯一区别:

Here's the only differences I see between the old layouts and the new:

旧的布局是AbsoluteLayouts的复杂混乱.看起来像这样,我没有写:

The old layouts were a complicated mess of AbsoluteLayouts. It looked something like this, I didn't write it:

<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,其中包含与该叠加层相关的元素.这些布局都以周期互相引用,并且随着布局事件的变化而相互更新.最终,这是一个令人着迷的乒乓球.通常.有时事情只是消失.显然,有一个原因我要重写它.

The main layout contains AbsoluteLayouts to constrain the child views. One child view is itself an AbsoluteLayout that contains the Map and a handful of other elements associated with it. The other child is the overlay, which is always an AbsoluteLayout that contains the elements relevant to that overlay. These layouts all reference each other in cycles and update each other as layout events change. It's a fascinating ping-ponging that eventually settles down. Usually. Sometimes things just disapper. Obviously there's a reason I'm rewriting it.

但是我可以在每个图层上单击需要单击的内容,但我不明白.

But I can click on what I need to click on at every layer, and I don't get that.

所以,让我们谈谈我需要工作的地方,也许弄清楚是不是它为什么不起作用的错误,还是与其他布局一起工作的巧合.这是一个非XAML页面布局,展示了我的项目起源于您无法在共享库中使用XAML的时代:

So, let's talk about what I need to work, and maybe figure out if it's a bug why it's not working, or if it's a coincidence that it worked with other layouts. Here's a non-XAML page layout that demonstrates, my project's got its roots in the days when you couldn't use XAML in shared libraries:

我需要能够在此UI中同时点击两个按钮并使它们响应.

I need to be able to tap both buttons in this UI and have them respond.

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;
    }
}

即使我将网格更改为AbsoluteLayout,这也只允许我点击覆盖"按钮.

This only lets me tap the "overlaying" button even when I change the Grid to an AbsoluteLayout.

我很困惑.我花了2个星期的时间来调试初始布局并提出新的解决方案.我真的不想分解我们所有的布局并将所有内容放在一个大的AbsoluteLayout或自定义布局中.在WPF中,有两种透明类​​型:透明背景"意味着背景仍然可以通过测试,而空背景"意味着背景不会通过测试.有没有办法像这样在Xamarin中叠加布局?

I'm stumped. It took me 2 weeks to debug the initial layouts and come up with a new solution. I really don't want to disassemble all of our layouts and put everything in one big AbsoluteLayout or a custom layout. In WPF, there were two kinds of transparent: "transparent background" meant the background could still hit test, and "null background" meant the background would not hit test. Is there some way to overlay layouts in Xamarin like this?

或更恰当的是,为什么旧​​布局中众多AbsoluteLayouts的复杂嵌套像我需要的那样工作,但是这种简单得多的布局却不是吗?

Or, more appropriate, why is the convoluted nest of numerous AbsoluteLayouts in our old layouts working like I need it to, but this much simpler layout isn't?

更新

这里我还记得一些其他信息:

Here's some additional information I remembered:

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆