зеркало из https://github.com/DeGsoft/maui-linux.git
* [Android] Prevent bubbled gestures from falling through to controls behind transparent containers; fixes #2858 * Remove XAMLC attribute
This commit is contained in:
Родитель
c79c77dbdf
Коммит
b4da374c73
|
@ -0,0 +1,34 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<controls:TestContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:controls="clr-namespace:Xamarin.Forms.Controls;assembly=Xamarin.Forms.Controls"
|
||||
x:Class="Xamarin.Forms.Controls.Issues.Issue2858">
|
||||
<ContentPage.Content>
|
||||
<Grid>
|
||||
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" ></RowDefinition>
|
||||
<RowDefinition Height="Auto" ></RowDefinition>
|
||||
<RowDefinition Height="*" ></RowDefinition>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<Label Text="Tap the red box below. Then tap the green area outside the box. If 'Success' is visible below, this test has passed."></Label>
|
||||
|
||||
<Label Grid.Row="1" Text="Running..." x:Name="Result"></Label>
|
||||
|
||||
<Grid Grid.Row="2" BackgroundColor="Blue" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand"
|
||||
AutomationId="TapGrid">
|
||||
<Grid.GestureRecognizers>
|
||||
<TapGestureRecognizer Tapped="TapGestureRecognizer_OnTapped" />
|
||||
</Grid.GestureRecognizers>
|
||||
</Grid>
|
||||
<Grid Grid.Row="2" RowSpacing="0" ColumnSpacing="0" InputTransparent="True" CascadeInputTransparent="False"
|
||||
Padding="10" BackgroundColor="Green" AutomationId="OuterGrid">
|
||||
<Grid BackgroundColor="Red" HorizontalOptions="Center" WidthRequest="300" VerticalOptions="Center"
|
||||
HeightRequest="300" AutomationId="InnerGrid">
|
||||
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</ContentPage.Content>
|
||||
</controls:TestContentPage>
|
|
@ -0,0 +1,82 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Forms;
|
||||
|
||||
using Xamarin.Forms.CustomAttributes;
|
||||
using Xamarin.Forms.Internals;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
#if UITEST
|
||||
using Xamarin.Forms.Core.UITests;
|
||||
using Xamarin.UITest;
|
||||
using NUnit.Framework;
|
||||
#endif
|
||||
|
||||
namespace Xamarin.Forms.Controls.Issues
|
||||
{
|
||||
#if UITEST
|
||||
[Category(UITestCategories.InputTransparent)]
|
||||
[Category(UITestCategories.Gestures)]
|
||||
#endif
|
||||
|
||||
[Preserve(AllMembers = true)]
|
||||
[Issue(IssueTracker.Github, 2858, "Transparency Cascading", PlatformAffected.Android)]
|
||||
public partial class Issue2858 : TestContentPage
|
||||
{
|
||||
const string Success = "Success";
|
||||
const string Failure = "Fail";
|
||||
const string InnerGrid = "InnerGrid";
|
||||
const string OuterGrid = "OuterGrid";
|
||||
|
||||
#pragma warning disable CS0414
|
||||
int _tapCount = 0;
|
||||
#pragma warning restore CS0414
|
||||
|
||||
public Issue2858 ()
|
||||
{
|
||||
#if APP
|
||||
InitializeComponent ();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if APP
|
||||
void TapGestureRecognizer_OnTapped(object sender, EventArgs e)
|
||||
{
|
||||
_tapCount += 1;
|
||||
|
||||
if (_tapCount == 1)
|
||||
{
|
||||
Result.Text = Success;
|
||||
}
|
||||
else
|
||||
{
|
||||
Result.Text = Failure;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
protected override void Init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
#if UITEST
|
||||
[Test]
|
||||
public void CascadeInputTransparentGrids()
|
||||
{
|
||||
RunningApp.WaitForElement(InnerGrid);
|
||||
RunningApp.Tap(InnerGrid);
|
||||
|
||||
var green = RunningApp.WaitForElement(OuterGrid);
|
||||
RunningApp.TapCoordinates(green[0].Rect.CenterX, green[0].Rect.Y + 20);
|
||||
|
||||
RunningApp.WaitForElement(Success);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -328,6 +328,10 @@
|
|||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue2681.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue2858.xaml.cs">
|
||||
<DependentUpon>Issue2858.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue2929.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue2983.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Issue2963.cs" />
|
||||
|
@ -929,4 +933,10 @@
|
|||
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="$(MSBuildThisFileDirectory)Issue2858.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -1156,7 +1156,7 @@ namespace Xamarin.Forms.Platform.Android
|
|||
|
||||
internal class DefaultRenderer : VisualElementRenderer<View>
|
||||
{
|
||||
bool _notReallyHandled;
|
||||
public bool NotReallyHandled { get; private set; }
|
||||
IOnTouchListener _touchListener;
|
||||
|
||||
[Obsolete("This constructor is obsolete as of version 2.5. Please use DefaultRenderer(Context) instead.")]
|
||||
|
@ -1173,7 +1173,7 @@ namespace Xamarin.Forms.Platform.Android
|
|||
|
||||
internal void NotifyFakeHandling()
|
||||
{
|
||||
_notReallyHandled = true;
|
||||
NotReallyHandled = true;
|
||||
}
|
||||
|
||||
public override bool OnTouchEvent(MotionEvent e)
|
||||
|
@ -1216,11 +1216,11 @@ namespace Xamarin.Forms.Platform.Android
|
|||
// it then knows to ignore that result and return false/unhandled. This allows the event to propagate up the tree.
|
||||
#endregion
|
||||
|
||||
_notReallyHandled = false;
|
||||
NotReallyHandled = false;
|
||||
|
||||
var result = base.DispatchTouchEvent(e);
|
||||
|
||||
if (result && _notReallyHandled)
|
||||
if (result && NotReallyHandled)
|
||||
{
|
||||
// If the child control returned true from its touch event handler but signalled that it was a fake "true", then we
|
||||
// don't consider the event truly "handled" yet.
|
||||
|
|
|
@ -9,13 +9,13 @@ namespace Xamarin.Forms.Platform.Android
|
|||
|
||||
public bool HandleMotionEvent(IViewParent parent, MotionEvent motionEvent)
|
||||
{
|
||||
if (_isInViewCell || _element.InputTransparent || motionEvent.Action == MotionEventActions.Cancel)
|
||||
if (_isInViewCell || motionEvent.Action == MotionEventActions.Cancel)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var renderer = parent as Platform.DefaultRenderer;
|
||||
if (renderer == null)
|
||||
if (renderer == null || ShouldPassThroughElement())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -40,5 +40,45 @@ namespace Xamarin.Forms.Platform.Android
|
|||
// we don't fake handle the events because ListView needs them for row selection
|
||||
_isInViewCell = element.IsInViewCell();
|
||||
}
|
||||
|
||||
bool ShouldPassThroughElement()
|
||||
{
|
||||
if (_element is Layout layout)
|
||||
{
|
||||
if (!layout.InputTransparent)
|
||||
{
|
||||
// If the layout is not input transparent, then the event should not pass through it
|
||||
return false;
|
||||
}
|
||||
|
||||
if (layout.CascadeInputTransparent)
|
||||
{
|
||||
// This is a layout, and it's transparent, and all its children are transparent, then the event
|
||||
// can just pass through
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Platform.GetRenderer(_element) is Platform.DefaultRenderer renderer)
|
||||
{
|
||||
// If the event is being bubbled up from a child which is not inputtransparent, we do not want
|
||||
// it to be passed through (just up the tree)
|
||||
if (renderer.NotReallyHandled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// This event isn't being bubbled up by a non-InputTransparent child layout
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_element.InputTransparent)
|
||||
{
|
||||
// This is not a layout and it's transparent; the event can just pass through
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@ namespace Xamarin.Forms.Platform.Android
|
|||
string _defaultContentDescription;
|
||||
bool? _defaultFocusable;
|
||||
string _defaultHint;
|
||||
bool _inputTransparentInherited = true;
|
||||
bool _cascadeInputTransparent = true;
|
||||
|
||||
VisualElementPackager _packager;
|
||||
PropertyChangedEventHandler _propertyChangeHandler;
|
||||
|
@ -52,7 +52,7 @@ namespace Xamarin.Forms.Platform.Android
|
|||
|
||||
public override bool DispatchTouchEvent(MotionEvent e)
|
||||
{
|
||||
if (InputTransparent && _inputTransparentInherited)
|
||||
if (InputTransparent && _cascadeInputTransparent)
|
||||
{
|
||||
// If the Element is InputTransparent, this ViewGroup will be marked InputTransparent
|
||||
// If we're InputTransparent and our transparency should be applied to our child controls,
|
||||
|
@ -339,7 +339,7 @@ namespace Xamarin.Forms.Platform.Android
|
|||
return;
|
||||
}
|
||||
|
||||
_inputTransparentInherited = layout.CascadeInputTransparent;
|
||||
_cascadeInputTransparent = layout.CascadeInputTransparent;
|
||||
}
|
||||
|
||||
protected void SetPackager(VisualElementPackager packager)
|
||||
|
|
Загрузка…
Ссылка в новой задаче