diff --git a/Source/Details/_ASCollectionViewCell.mm b/Source/Details/_ASCollectionViewCell.mm index 28d8cec2a..93f4626a4 100644 --- a/Source/Details/_ASCollectionViewCell.mm +++ b/Source/Details/_ASCollectionViewCell.mm @@ -97,6 +97,9 @@ - (void)layoutSubviews - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { + ASCellNode *node = self.node; + UIView *nodeView = node.view; + /** * The documentation for hitTest:withEvent: on an UIView explicitly states the fact that: * it ignores view objects that are hidden, that have disabled user interactions, or have an @@ -106,12 +109,13 @@ - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event * superclass hitTest:withEvent: implementation. If this returns a valid value we can go on with * checking the node as it's expected to not be in one of these states. */ - if (![super hitTest:self.bounds.origin withEvent:event]) { + CGPoint originPointOnView = [self convertPoint:nodeView.bounds.origin fromView:nodeView]; + if (![super hitTest:originPointOnView withEvent:event]) { return nil; } - CGPoint pointOnNode = [self.node.view convertPoint:point fromView:self]; - return [self.node hitTest:pointOnNode withEvent:event]; + CGPoint pointOnNode = [node.view convertPoint:point fromView:self]; + return [node hitTest:pointOnNode withEvent:event]; } - (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event diff --git a/Tests/ASCollectionViewTests.mm b/Tests/ASCollectionViewTests.mm index 496c1feba..ab4779ea9 100644 --- a/Tests/ASCollectionViewTests.mm +++ b/Tests/ASCollectionViewTests.mm @@ -387,6 +387,31 @@ - (void)testThatCollectionNodeConformsToExpectedProtocols XCTAssert([node conformsToProtocol:@protocol(ASRangeControllerUpdateRangeProtocol)]); } +/** + * Test that hit tests are correct when the collection node is inverted. + */ +- (void)testInvertedCollectionViewHitTest +{ + ASCollectionViewTestController *testController = [[ASCollectionViewTestController alloc] initWithNibName:nil bundle:nil]; + UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + [window setRootViewController:testController]; + [window makeKeyAndVisible]; + + testController.collectionNode.inverted = true; + [testController.collectionNode reloadData]; + [testController.collectionNode waitUntilAllUpdatesAreProcessed]; + [testController.collectionView layoutIfNeeded]; + + NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; + UICollectionViewCell *cell = [testController.collectionView cellForItemAtIndexPath:indexPath]; + ASDisplayNode *node = [testController.collectionNode nodeForItemAtIndexPath:indexPath]; + + CGPoint testPointInCollectionView = CGPointMake(CGRectGetMidX(cell.frame), CGRectGetMidY(cell.frame)); + UIView *hitTestView = [testController.collectionView hitTest:testPointInCollectionView withEvent:nil]; + + XCTAssertEqualObjects(hitTestView, node.view, @"Expected node's view to be the result of the hit test."); +} + #pragma mark - Update Validations #define updateValidationTestPrologue \