mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Fix iOS platform view's mask view blocking touch events. (flutter/engine#21286)
This commit is contained in:
parent
0b0fe27af8
commit
73ae0bb94c
@ -90,6 +90,15 @@ void ResetAnchor(CALayer* layer) {
|
||||
return self;
|
||||
}
|
||||
|
||||
// In some scenarios, when we add this view as a maskView of the ChildClippingView, iOS added
|
||||
// this view as a subview of the ChildClippingView.
|
||||
// This results this view blocking touch events on the ChildClippingView.
|
||||
// So we should always ignore any touch events sent to this view.
|
||||
// See https://github.com/flutter/flutter/issues/66044
|
||||
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event {
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)drawRect:(CGRect)rect {
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
CGContextSaveGState(context);
|
||||
|
||||
@ -23,7 +23,9 @@
|
||||
- (BOOL)application:(UIApplication*)application
|
||||
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
|
||||
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||
|
||||
if ([[[NSProcessInfo processInfo] arguments] containsObject:@"--maskview-blocking"]) {
|
||||
self.window.tintColor = UIColor.systemPinkColor;
|
||||
}
|
||||
NSDictionary<NSString*, NSString*>* launchArgsMap = @{
|
||||
// The Platform view golden test args should match `PlatformViewGoldenTestManager`.
|
||||
@"--locale-initialization" : @"locale_initialization",
|
||||
@ -58,7 +60,6 @@
|
||||
*stop = YES;
|
||||
}
|
||||
}];
|
||||
|
||||
if (flutterViewControllerTestName) {
|
||||
[self setupFlutterViewControllerTest:flutterViewControllerTestName];
|
||||
} else if ([[[NSProcessInfo processInfo] arguments] containsObject:@"--screen-before-flutter"]) {
|
||||
|
||||
@ -110,9 +110,54 @@ static const NSInteger kSecondsToWaitForPlatformView = 30;
|
||||
[[XCTNSPredicateExpectation alloc] initWithPredicate:predicate object:platformView];
|
||||
|
||||
[platformView tap];
|
||||
|
||||
[self waitForExpectations:@[ expection ] timeout:kSecondsToWaitForPlatformView];
|
||||
XCTAssertEqualObjects(platformView.label,
|
||||
@"-gestureTouchesBegan-gestureTouchesEnded-platformViewTapped");
|
||||
}
|
||||
|
||||
- (void)testGestureWithMaskViewBlockingPlatformView {
|
||||
XCUIApplication* app = [[XCUIApplication alloc] init];
|
||||
app.launchArguments = @[ @"--gesture-accept", @"--maskview-blocking" ];
|
||||
[app launch];
|
||||
|
||||
NSPredicate* predicateToFindPlatformView =
|
||||
[NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject,
|
||||
NSDictionary<NSString*, id>* _Nullable bindings) {
|
||||
XCUIElement* element = evaluatedObject;
|
||||
return [element.identifier hasPrefix:@"platform_view"];
|
||||
}];
|
||||
XCUIElement* platformView = [app.textViews elementMatchingPredicate:predicateToFindPlatformView];
|
||||
if (![platformView waitForExistenceWithTimeout:kSecondsToWaitForPlatformView]) {
|
||||
NSLog(@"%@", app.debugDescription);
|
||||
XCTFail(@"Failed due to not able to find any platformView with %@ seconds",
|
||||
@(kSecondsToWaitForPlatformView));
|
||||
}
|
||||
|
||||
XCTAssertNotNil(platformView);
|
||||
XCTAssertEqualObjects(platformView.label, @"");
|
||||
|
||||
NSPredicate* predicate = [NSPredicate
|
||||
predicateWithFormat:@"label == %@",
|
||||
@"-gestureTouchesBegan-gestureTouchesEnded-platformViewTapped"];
|
||||
XCTNSPredicateExpectation* expection =
|
||||
[[XCTNSPredicateExpectation alloc] initWithPredicate:predicate object:platformView];
|
||||
|
||||
XCUICoordinate* coordinate =
|
||||
[self getNormalizedCoordinate:app
|
||||
point:CGVectorMake(platformView.frame.origin.x + 10,
|
||||
platformView.frame.origin.y + 10)];
|
||||
[coordinate tap];
|
||||
|
||||
[self waitForExpectations:@[ expection ] timeout:kSecondsToWaitForPlatformView];
|
||||
XCTAssertEqualObjects(platformView.label,
|
||||
@"-gestureTouchesBegan-gestureTouchesEnded-platformViewTapped");
|
||||
}
|
||||
|
||||
- (XCUICoordinate*)getNormalizedCoordinate:(XCUIApplication*)app point:(CGVector)vector {
|
||||
XCUICoordinate* appZero = [app coordinateWithNormalizedOffset:CGVectorMake(0, 0)];
|
||||
XCUICoordinate* coordinate = [appZero coordinateWithOffset:vector];
|
||||
return coordinate;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@ -336,9 +336,9 @@ class MultiPlatformViewBackgroundForegroundScenario extends Scenario with _BaseP
|
||||
MultiPlatformViewBackgroundForegroundScenario(Window window, {this.firstId, this.secondId})
|
||||
: assert(window != null),
|
||||
super(window) {
|
||||
_nextFrame = _firstFrame;
|
||||
createPlatformView(window, 'platform view 1', firstId);
|
||||
createPlatformView(window, 'platform view 2', secondId);
|
||||
_nextFrame = _firstFrame;
|
||||
}
|
||||
|
||||
/// The platform view identifier to use for the first platform view.
|
||||
@ -532,6 +532,8 @@ class PlatformViewForTouchIOSScenario extends Scenario
|
||||
|
||||
int _viewId;
|
||||
bool _accept;
|
||||
|
||||
VoidCallback _nextFrame;
|
||||
/// Creates the PlatformView scenario.
|
||||
///
|
||||
/// The [window] parameter must not be null.
|
||||
@ -545,14 +547,24 @@ class PlatformViewForTouchIOSScenario extends Scenario
|
||||
} else {
|
||||
createPlatformView(window, text, id);
|
||||
}
|
||||
_nextFrame = _firstFrame;
|
||||
}
|
||||
|
||||
@override
|
||||
void onBeginFrame(Duration duration) {
|
||||
final SceneBuilder builder = SceneBuilder();
|
||||
_nextFrame();
|
||||
}
|
||||
|
||||
builder.pushOffset(0, 0);
|
||||
finishBuilderByAddingPlatformViewAndPicture(builder, _viewId);
|
||||
@override
|
||||
void onDrawFrame() {
|
||||
// Some iOS gesture recognizers bugs are introduced in the second frame (with a different platform view rect) after laying out the platform view.
|
||||
// So in this test, we load 2 frames to ensure that we cover those cases.
|
||||
// See https://github.com/flutter/flutter/issues/66044
|
||||
if (_nextFrame == _firstFrame) {
|
||||
_nextFrame = _secondFrame;
|
||||
window.scheduleFrame();
|
||||
}
|
||||
super.onDrawFrame();
|
||||
}
|
||||
|
||||
@override
|
||||
@ -585,6 +597,20 @@ class PlatformViewForTouchIOSScenario extends Scenario
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void _firstFrame() {
|
||||
final SceneBuilder builder = SceneBuilder();
|
||||
|
||||
builder.pushOffset(0, 0);
|
||||
finishBuilderByAddingPlatformViewAndPicture(builder, _viewId);
|
||||
}
|
||||
|
||||
void _secondFrame() {
|
||||
final SceneBuilder builder = SceneBuilder();
|
||||
|
||||
builder.pushOffset(5, 5);
|
||||
finishBuilderByAddingPlatformViewAndPicture(builder, _viewId);
|
||||
}
|
||||
}
|
||||
|
||||
mixin _BasePlatformViewScenarioMixin on Scenario {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user