Skip to content

Commit

Permalink
Fix hit point when ASCollectionNode inverted set to true (#1781)
Browse files Browse the repository at this point in the history
* Account for possible inverted transform during hit test

When ASCollectionNode has the `inverted` flag set, a transform gets
set on the cell node. We need to make sure that we account for that
when dealing in the view coordinates.

* Store self.node and self.node.view in local variables for better readability.

* Add a test for hit testing in an inverted ASCollectionNode
  • Loading branch information
bdolman committed Oct 6, 2020
1 parent 5a205d8 commit efdd8ac
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 3 deletions.
10 changes: 7 additions & 3 deletions Source/Details/_ASCollectionViewCell.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
25 changes: 25 additions & 0 deletions Tests/ASCollectionViewTests.mm
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand Down

0 comments on commit efdd8ac

Please sign in to comment.