Bug 59933 - RelativeLayout with InputTransparent = true occluding RelativeLayout beneath
Summary: RelativeLayout with InputTransparent = true occluding RelativeLayout beneath
Status: RESOLVED ANSWERED
Alias: None
Product: Forms
Classification: Xamarin
Component: Forms (show other bugs)
Version: 2.4.0
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: ---
Assignee: E.Z. Hart [MSFT]
URL:
Depends on:
Blocks:
 
Reported: 2017-10-03 18:06 UTC by Daniel Robbins
Modified: 2017-10-08 23:37 UTC (History)
2 users (show)

See Also:
Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Working version of sample code (297.34 KB, application/x-zip-compressed)
2017-10-06 20:12 UTC, E.Z. Hart [MSFT]
Details

Description Daniel Robbins 2017-10-03 18:06:24 UTC
I am using Xamarin Forms 2.4.0.282. 

I am using a technique where I have two RelativeLayouts that are part of a Grid -- in fact, they have been added to the same part of the grid. One, the lower RelativeLayout (slidein_layout) is offset, out of the visible area so it cannot be seen, and scrolls in from off-screen for a dynamic effect, while the other (static_layout) contains elements that do not move. Both RelativeLayouts contain children that receive input. In my case, I have Tap Gesture Recognizer in bottom right corner of the top RelativeLayout, and I have Entry and Picker elements in the RelativeLayout beneath. I have used RelativeLayout functionality so that after slidein_layout has transitioned to its final location, input elements from both RelativeLayouts are visible and not overlapping one another. 

The issue I experience is that the top RelativeLayout (static_layout) will receive all input events, and nothing in the lower RelativeLayout (slidein_layout) will at all. This is true *even if* I set InputTransparent = true on the top RelativeLayout. So the entire area of the top RelativeLayout occludes the bottom RelativeLayout from any input.

While the behavior of InputTransparent is not entirely clear to me, I would expect one of two behaviors, which to me would make sense:

1) Setting InputTransparent on the top RelativeLayout would allow it to pass input events to the RelativeLayout (and its children) below, *if* one of its own children did not handle the Input event itself. This would be my preferred behavior.

2) Setting InputTransparent on the top RelativeLayout would apply to the top RelativeLayout *and all its children*, and any input would not be handled by the InputTransparent RelativeLayout but instead go to the RelativeLayout underneath. This would at least make sense, if one decided that InputTransparent, when applied to a Layout, also transitively applied to all its children. However, this would be far less flexible as it would not allow individual InputTransparent settings applied to the children, so #1 would be strongly preferred.

If neither #1 or #2 is the desired behavior of InputTransparent when applied to Layouts, then we at the very least need some clarification of how InputTransparent behaves in this scenario, and clarification to the documentation so that Forms users can easily understand what to expect when it comes to input occlusion.
Comment 1 Daniel Robbins 2017-10-03 18:20:13 UTC
To clarify, I am actually not moving the slidein_layout, which is integrated into an on-screen grid. It has a StackLayout within it that contains all elements, that is initially offset so it is not visible, and then TransitionTo is used to move the StackLayout and associated elements within the bounds of the parent RelativeLayout.

For the static_layout, this is a RelativeLayout and the child input element is a StackLayout that has been turned into an input element via a TapGestureRecognizer.

To me, the details of the slidein_layout in the first paragraph shouldn't matter too much, as the static_layout on top is simply occluding everything underneath even with InputTransparent = true set on the static_layout.
Comment 3 Daniel Robbins 2017-10-05 23:45:51 UTC
Yes, see here where I posted some sample code that is failing:

https://forums.xamarin.com/discussion/comment/300167/#Comment_300167
Comment 4 E.Z. Hart [MSFT] 2017-10-06 20:12:09 UTC
Created attachment 25179 [details]
Working version of sample code

Daniel,

I tried your code on previous versions of XF back to 1.5, and I can't find a version where it works. 

The main issue is that the Picker is initially laid out offscreen and then translated onto the screen; even after translating it onto the screen, the control's input layout remains off screen and the user can't interact with it. An alternative way to accomplish the effect you're aiming for is to initially lay out the control on screen, translate the control off screen, and then translate the control back to the on-screen position (i.e., calling .TranslateTo(0,0) when you want it animated onto the screen. At this point, the visible position of the control and its input layout will match, and the user can interact with it. 

I'm attaching a project with a slightly modified version of your code which uses this method to animate the control onto the screen.

You are correct that with the two overlapping RelativeLayouts, the top layout prevents the bottom layout from receiving input. And if the top layout is marked InputTransparent, it also makes the "Next" button InputTransparent, preventing it from being clicked. In the attached project I've worked around this by putting all of the controls in a single RelativeLayout.
Comment 5 Daniel Robbins 2017-10-06 21:09:58 UTC
I believe that I had a version that worked, the Forms upgrade broke it, and then I rewrote the version to use two RelativeLayouts as in the demo code, which apparently is never supposed to work.

Please consider adding some functionality to allow my code to work as-is or with very minor modifications. The current behavior is not intuitive. Users expect to be able to translate something and not have it break. They just want it to work.

In other words, by supporting arbitrary transitions of input elements, you will allow users to focus on the behavior of their app rather than the peculiarities of Xamarin Forms implementation.

Some ideas on how to gracefully address this -- a call that can be made to say 'Everything is in its final location'. This is straightforward. Users who translate input elements can then be instructed to make this call to tell Forms to update the position of the input elements so that re-aligning with their original location (what I consider a 'hack') is not necessary. This gives the programmer the ability to do translations as they see fit and not worry about shuffling everything back to its original location.

Another idea -- auto-update the layout of input elements after every TranslateTo call. Possibly slower but would eliminate to make the manual call at all.
Comment 6 Daniel Robbins 2017-10-08 23:37:44 UTC
Also, thanks very much for the fixed code. I do appreciate it. Please consider my request as a feature enhancement rather than a bug -- I doubt I will be the last who will encounter this particular quirk of Forms.

Note You need to log in before you can comment on or make changes to this bug.