mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-12-23 22:55:00 +00:00
[AsyncDisplayKit+Debug.h] Moving hitTestDebug tool code out of ASControlNode and into debug file
- unifying ASControlNode, ASImageNode debugging categories into debug file to simplify base classes
This commit is contained in:
@@ -11,6 +11,8 @@
|
|||||||
#import "ASThread.h"
|
#import "ASThread.h"
|
||||||
#import "ASDisplayNodeExtras.h"
|
#import "ASDisplayNodeExtras.h"
|
||||||
#import "ASImageNode.h"
|
#import "ASImageNode.h"
|
||||||
|
#import "AsyncDisplayKit+Debug.h"
|
||||||
|
#import "ASInternalHelpers.h"
|
||||||
|
|
||||||
// UIControl allows dragging some distance outside of the control itself during
|
// UIControl allows dragging some distance outside of the control itself during
|
||||||
// tracking. This value depends on the device idiom (25 or 70 points), so
|
// tracking. This value depends on the device idiom (25 or 70 points), so
|
||||||
@@ -71,8 +73,6 @@ void _ASEnumerateControlEventsIncludedInMaskWithBlock(ASControlNodeEvent mask, v
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
static BOOL _enableHitTestDebug = NO;
|
|
||||||
|
|
||||||
@implementation ASControlNode
|
@implementation ASControlNode
|
||||||
{
|
{
|
||||||
ASImageNode *_debugHighlightOverlay;
|
ASImageNode *_debugHighlightOverlay;
|
||||||
@@ -262,14 +262,15 @@ static BOOL _enableHitTestDebug = NO;
|
|||||||
_controlEventDispatchTable = [[NSMutableDictionary alloc] initWithCapacity:kASControlNodeEventDispatchTableInitialCapacity]; // enough to handle common types without re-hashing the dictionary when adding entries.
|
_controlEventDispatchTable = [[NSMutableDictionary alloc] initWithCapacity:kASControlNodeEventDispatchTableInitialCapacity]; // enough to handle common types without re-hashing the dictionary when adding entries.
|
||||||
|
|
||||||
// only show tap-able areas for views with 1 or more addTarget:action: pairs
|
// only show tap-able areas for views with 1 or more addTarget:action: pairs
|
||||||
if (_enableHitTestDebug) {
|
if ([ASControlNode enableHitTestDebug]) {
|
||||||
|
ASPerformBlockOnMainThread(^{
|
||||||
// add a highlight overlay node with area of ASControlNode + UIEdgeInsets
|
// add a highlight overlay node with area of ASControlNode + UIEdgeInsets
|
||||||
self.clipsToBounds = NO;
|
self.clipsToBounds = NO;
|
||||||
_debugHighlightOverlay = [[ASImageNode alloc] init];
|
_debugHighlightOverlay = [[ASImageNode alloc] init];
|
||||||
_debugHighlightOverlay.zPosition = 1000; // CALayer doesn't have -moveSublayerToFront, but this will ensure we're over the top of any siblings.
|
_debugHighlightOverlay.zPosition = 1000; // ensure we're over the top of any siblings
|
||||||
_debugHighlightOverlay.layerBacked = YES;
|
_debugHighlightOverlay.layerBacked = YES;
|
||||||
[self addSubnode:_debugHighlightOverlay];
|
[self addSubnode:_debugHighlightOverlay];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -470,134 +471,9 @@ void _ASEnumerateControlEventsIncludedInMaskWithBlock(ASControlNodeEvent mask, v
|
|||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - Debug
|
#pragma mark - Debug
|
||||||
// Layout method required when _enableHitTestDebug is enabled.
|
- (ASImageNode *)debugHighlightOverlay
|
||||||
- (void)layout
|
|
||||||
{
|
{
|
||||||
[super layout];
|
return _debugHighlightOverlay;
|
||||||
|
|
||||||
if (_debugHighlightOverlay) {
|
|
||||||
|
|
||||||
// Even if our parents don't have clipsToBounds set and would allow us to display the debug overlay, UIKit event delivery (hitTest:)
|
|
||||||
// will not search sub-hierarchies if one of our parents does not return YES for pointInside:. In such a scenario, hitTestSlop
|
|
||||||
// may not be able to expand the tap target as much as desired without also setting some hitTestSlop on the limiting parents.
|
|
||||||
CGRect intersectRect = UIEdgeInsetsInsetRect(self.bounds, [self hitTestSlop]);
|
|
||||||
UIRectEdge clippedEdges = UIRectEdgeNone;
|
|
||||||
UIRectEdge clipsToBoundsClippedEdges = UIRectEdgeNone;
|
|
||||||
CALayer *layer = self.layer;
|
|
||||||
CALayer *intersectLayer = layer;
|
|
||||||
CALayer *intersectSuperlayer = layer.superlayer;
|
|
||||||
|
|
||||||
// Stop climbing if we encounter a UIScrollView, as its offset bounds origin may make it seem like our events will be clipped when
|
|
||||||
// scrolling will actually reveal them (because this process will not re-run due to scrolling)
|
|
||||||
while (intersectSuperlayer && ![intersectSuperlayer.delegate respondsToSelector:@selector(contentOffset)]) {
|
|
||||||
// Get our parent's tappable bounds. If the parent has an associated node, consider hitTestSlop, as it will extend its pointInside:.
|
|
||||||
CGRect parentHitRect = intersectSuperlayer.bounds;
|
|
||||||
BOOL parentClipsToBounds = NO;
|
|
||||||
|
|
||||||
ASDisplayNode *parentNode = ASLayerToDisplayNode(intersectSuperlayer);
|
|
||||||
if (parentNode) {
|
|
||||||
UIEdgeInsets parentSlop = [parentNode hitTestSlop];
|
|
||||||
|
|
||||||
// if parent has a hitTestSlop as well, we need to account for the fact that events will be routed towards us in that area too.
|
|
||||||
if (!UIEdgeInsetsEqualToEdgeInsets(UIEdgeInsetsZero, parentSlop)) {
|
|
||||||
parentClipsToBounds = parentNode.clipsToBounds;
|
|
||||||
// if the parent is clipping, this will prevent us from showing the overlay outside that area.
|
|
||||||
// in this case, we will make the overlay smaller so that the special highlight to indicate the overlay
|
|
||||||
// cannot accurately display the true tappable area is shown.
|
|
||||||
if (!parentClipsToBounds) {
|
|
||||||
parentHitRect = UIEdgeInsetsInsetRect(parentHitRect, [parentNode hitTestSlop]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert our current rectangle to parent coordinates, and intersect with the parent's hit rect.
|
|
||||||
CGRect intersectRectInParentCoordinates = [intersectSuperlayer convertRect:intersectRect fromLayer:intersectLayer];
|
|
||||||
intersectRect = CGRectIntersection(parentHitRect, intersectRectInParentCoordinates);
|
|
||||||
if (!CGSizeEqualToSize(parentHitRect.size, intersectRectInParentCoordinates.size)) {
|
|
||||||
clippedEdges = [self setEdgesOfIntersectionForChildRect:intersectRectInParentCoordinates
|
|
||||||
parentRect:parentHitRect rectEdge:clippedEdges];
|
|
||||||
if (parentClipsToBounds) {
|
|
||||||
clipsToBoundsClippedEdges = [self setEdgesOfIntersectionForChildRect:intersectRectInParentCoordinates
|
|
||||||
parentRect:parentHitRect rectEdge:clipsToBoundsClippedEdges];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Advance up the tree.
|
|
||||||
intersectLayer = intersectSuperlayer;
|
|
||||||
intersectSuperlayer = intersectLayer.superlayer;
|
|
||||||
}
|
|
||||||
|
|
||||||
CGRect finalRect = [intersectLayer convertRect:intersectRect toLayer:layer];
|
|
||||||
UIColor *fillColor = [[UIColor greenColor] colorWithAlphaComponent:0.4];
|
|
||||||
|
|
||||||
// determine if edges are clipped
|
|
||||||
if (clippedEdges == UIRectEdgeNone) {
|
|
||||||
_debugHighlightOverlay.backgroundColor = fillColor;
|
|
||||||
} else {
|
|
||||||
const CGFloat borderWidth = 2.0;
|
|
||||||
UIColor *borderColor = [[UIColor orangeColor] colorWithAlphaComponent:0.8];
|
|
||||||
UIColor *clipsBorderColor = [UIColor colorWithRed:30/255.0 green:90/255.0 blue:50/255.0 alpha:0.7];
|
|
||||||
CGRect imgRect = CGRectMake(0, 0, 2.0 * borderWidth + 1.0, 2.0 * borderWidth + 1.0);
|
|
||||||
UIGraphicsBeginImageContext(imgRect.size);
|
|
||||||
|
|
||||||
[fillColor setFill];
|
|
||||||
UIRectFill(imgRect);
|
|
||||||
|
|
||||||
[self drawEdgeIfClippedWithEdges:clippedEdges color:clipsBorderColor borderWidth:borderWidth imgRect:imgRect];
|
|
||||||
[self drawEdgeIfClippedWithEdges:clipsToBoundsClippedEdges color:borderColor borderWidth:borderWidth imgRect:imgRect];
|
|
||||||
|
|
||||||
UIImage *debugHighlightImage = UIGraphicsGetImageFromCurrentImageContext();
|
|
||||||
UIGraphicsEndImageContext();
|
|
||||||
|
|
||||||
UIEdgeInsets edgeInsets = UIEdgeInsetsMake(borderWidth, borderWidth, borderWidth, borderWidth);
|
|
||||||
_debugHighlightOverlay.image = [debugHighlightImage resizableImageWithCapInsets:edgeInsets
|
|
||||||
resizingMode:UIImageResizingModeStretch];
|
|
||||||
_debugHighlightOverlay.backgroundColor = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
_debugHighlightOverlay.frame = finalRect;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (UIRectEdge)setEdgesOfIntersectionForChildRect:(CGRect)childRect parentRect:(CGRect)parentRect rectEdge:(UIRectEdge)rectEdge
|
|
||||||
{
|
|
||||||
if (childRect.origin.y < parentRect.origin.y) {
|
|
||||||
rectEdge |= UIRectEdgeTop;
|
|
||||||
}
|
|
||||||
if (childRect.origin.x < parentRect.origin.x) {
|
|
||||||
rectEdge |= UIRectEdgeLeft;
|
|
||||||
}
|
|
||||||
if (CGRectGetMaxY(childRect) > CGRectGetMaxY(parentRect)) {
|
|
||||||
rectEdge |= UIRectEdgeBottom;
|
|
||||||
}
|
|
||||||
if (CGRectGetMaxX(childRect) > CGRectGetMaxX(parentRect)) {
|
|
||||||
rectEdge |= UIRectEdgeRight;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rectEdge;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)drawEdgeIfClippedWithEdges:(UIRectEdge)rectEdge color:(UIColor *)color borderWidth:(CGFloat)borderWidth imgRect:(CGRect)imgRect
|
|
||||||
{
|
|
||||||
[color setFill];
|
|
||||||
|
|
||||||
if (rectEdge & UIRectEdgeTop) {
|
|
||||||
UIRectFill(CGRectMake(0.0, 0.0, imgRect.size.width, borderWidth));
|
|
||||||
}
|
|
||||||
if (rectEdge & UIRectEdgeLeft) {
|
|
||||||
UIRectFill(CGRectMake(0.0, 0.0, borderWidth, imgRect.size.height));
|
|
||||||
}
|
|
||||||
if (rectEdge & UIRectEdgeBottom) {
|
|
||||||
UIRectFill(CGRectMake(0.0, imgRect.size.height - borderWidth, imgRect.size.width, borderWidth));
|
|
||||||
}
|
|
||||||
if (rectEdge & UIRectEdgeRight) {
|
|
||||||
UIRectFill(CGRectMake(imgRect.size.width - borderWidth, 0.0, borderWidth, imgRect.size.height));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (void)setEnableHitTestDebug:(BOOL)enable
|
|
||||||
{
|
|
||||||
_enableHitTestDebug = enable;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -9,6 +9,19 @@
|
|||||||
#import "ASControlNode.h"
|
#import "ASControlNode.h"
|
||||||
#import "ASImageNode.h"
|
#import "ASImageNode.h"
|
||||||
|
|
||||||
|
@interface ASImageNode (Debugging)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables an ASImageNode debug label that shows the ratio of pixels in the source image to those in
|
||||||
|
* the displayed bounds (including cropRect). This helps detect excessive image fetching / downscaling,
|
||||||
|
* as well as upscaling (such as providing a URL not suitable for a Retina device). For dev purposes only.
|
||||||
|
* @param enabled Specify YES to show the label on all ASImageNodes with non-1.0x source-to-bounds pixel ratio.
|
||||||
|
*/
|
||||||
|
+ (void)setShouldShowImageScalingOverlay:(BOOL)show;
|
||||||
|
+ (BOOL)shouldShowImageScalingOverlay;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
@interface ASControlNode (Debugging)
|
@interface ASControlNode (Debugging)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,18 +34,7 @@
|
|||||||
@param enable Specify YES to make this debug feature enabled when messaging the ASControlNode class.
|
@param enable Specify YES to make this debug feature enabled when messaging the ASControlNode class.
|
||||||
*/
|
*/
|
||||||
+ (void)setEnableHitTestDebug:(BOOL)enable;
|
+ (void)setEnableHitTestDebug:(BOOL)enable;
|
||||||
|
+ (BOOL)enableHitTestDebug;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface ASImageNode (Debugging)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Enables an ASImageNode debug label that shows the ratio of pixels in the source image to those in
|
|
||||||
* the displayed bounds (including cropRect). This helps detect excessive image fetching / downscaling,
|
|
||||||
* as well as upscaling (such as providing a URL not suitable for a Retina device). For dev purposes only.
|
|
||||||
* @param enabled Specify YES to show the label on all ASImageNodes with non-1.0x source-to-bounds pixel ratio.
|
|
||||||
*/
|
|
||||||
+ (void)setShouldShowImageScalingOverlay:(BOOL)show;
|
|
||||||
+ (BOOL)shouldShowImageScalingOverlay;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#import "AsyncDisplayKit+Debug.h"
|
#import "AsyncDisplayKit+Debug.h"
|
||||||
#import "ASDisplayNode+Subclasses.h"
|
#import "ASDisplayNode+Subclasses.h"
|
||||||
|
#import "ASDisplayNodeExtras.h"
|
||||||
|
|
||||||
static BOOL __shouldShowImageScalingOverlay = NO;
|
static BOOL __shouldShowImageScalingOverlay = NO;
|
||||||
|
|
||||||
@@ -24,3 +25,165 @@ static BOOL __shouldShowImageScalingOverlay = NO;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
static BOOL __enableHitTestDebug = NO;
|
||||||
|
|
||||||
|
@interface ASControlNode (Debugging)
|
||||||
|
|
||||||
|
- (ASImageNode *)debugHighlightOverlay;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation ASControlNode (Debugging)
|
||||||
|
|
||||||
|
+ (void)setEnableHitTestDebug:(BOOL)enable
|
||||||
|
{
|
||||||
|
__enableHitTestDebug = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (BOOL)enableHitTestDebug
|
||||||
|
{
|
||||||
|
return __enableHitTestDebug;
|
||||||
|
}
|
||||||
|
|
||||||
|
// layout method required ONLY when hitTestDebug is enabled
|
||||||
|
- (void)layout
|
||||||
|
{
|
||||||
|
[super layout];
|
||||||
|
|
||||||
|
if ([ASControlNode enableHitTestDebug]) {
|
||||||
|
|
||||||
|
// Construct hitTestDebug highlight overlay frame indicating tappable area of a node, which can be restricted by two things:
|
||||||
|
|
||||||
|
// (1) Any parent's tapable area (its own bounds + hitTestSlop) may restrict the desired tappable area expansion using
|
||||||
|
// hitTestSlop of a child as UIKit event delivery (hitTest:) will not search sub-hierarchies if one of our parents does
|
||||||
|
// not return YES for pointInside:. To circumvent this restriction, a developer will need to set / adjust the hitTestSlop
|
||||||
|
// on the limiting parent. This is indicated in the overlay by a dark GREEN edge. This is an ACTUAL restriction.
|
||||||
|
|
||||||
|
// (2) Any parent's .clipToBounds. If a parent is clipping, we cannot show the overlay outside that area
|
||||||
|
// (although it still respond to touch). To indicate that the overlay cannot accurately display the true tappable area,
|
||||||
|
// the overlay will have an ORANGE edge. This is a VISUALIZATION restriction.
|
||||||
|
|
||||||
|
CGRect intersectRect = UIEdgeInsetsInsetRect(self.bounds, [self hitTestSlop]);
|
||||||
|
UIRectEdge clippedEdges = UIRectEdgeNone;
|
||||||
|
UIRectEdge clipsToBoundsClippedEdges = UIRectEdgeNone;
|
||||||
|
CALayer *layer = self.layer;
|
||||||
|
CALayer *intersectLayer = layer;
|
||||||
|
CALayer *intersectSuperlayer = layer.superlayer;
|
||||||
|
|
||||||
|
// FIXED: Stop climbing hierarchy if UIScrollView is encountered (its offset bounds origin may make it seem like our events
|
||||||
|
// will be clipped when scrolling will actually reveal them (because this process will not re-run due to scrolling))
|
||||||
|
while (intersectSuperlayer && ![intersectSuperlayer.delegate respondsToSelector:@selector(contentOffset)]) {
|
||||||
|
|
||||||
|
// Get parent's tappable area
|
||||||
|
CGRect parentHitRect = intersectSuperlayer.bounds;
|
||||||
|
BOOL parentClipsToBounds = NO;
|
||||||
|
|
||||||
|
// If parent is a node, tappable area may be expanded by hitTestSlop
|
||||||
|
ASDisplayNode *parentNode = ASLayerToDisplayNode(intersectSuperlayer);
|
||||||
|
if (parentNode) {
|
||||||
|
UIEdgeInsets parentSlop = [parentNode hitTestSlop];
|
||||||
|
|
||||||
|
// If parent has hitTestSlop, expand tappable area (if parent doesn't clipToBounds)
|
||||||
|
if (!UIEdgeInsetsEqualToEdgeInsets(UIEdgeInsetsZero, parentSlop)) {
|
||||||
|
parentClipsToBounds = parentNode.clipsToBounds;
|
||||||
|
if (!parentClipsToBounds) {
|
||||||
|
parentHitRect = UIEdgeInsetsInsetRect(parentHitRect, [parentNode hitTestSlop]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert our current rect to parent coordinates
|
||||||
|
CGRect intersectRectInParentCoordinates = [intersectSuperlayer convertRect:intersectRect fromLayer:intersectLayer];
|
||||||
|
|
||||||
|
// Intersect rect with the parent's tappable area rect
|
||||||
|
intersectRect = CGRectIntersection(parentHitRect, intersectRectInParentCoordinates);
|
||||||
|
if (!CGSizeEqualToSize(parentHitRect.size, intersectRectInParentCoordinates.size)) {
|
||||||
|
clippedEdges = [self setEdgesOfIntersectionForChildRect:intersectRectInParentCoordinates
|
||||||
|
parentRect:parentHitRect rectEdge:clippedEdges];
|
||||||
|
if (parentClipsToBounds) {
|
||||||
|
clipsToBoundsClippedEdges = [self setEdgesOfIntersectionForChildRect:intersectRectInParentCoordinates
|
||||||
|
parentRect:parentHitRect rectEdge:clipsToBoundsClippedEdges];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// move up hierarchy
|
||||||
|
intersectLayer = intersectSuperlayer;
|
||||||
|
intersectSuperlayer = intersectLayer.superlayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// produce final overlay image (or fill background if edges aren't restricted)
|
||||||
|
CGRect finalRect = [intersectLayer convertRect:intersectRect toLayer:layer];
|
||||||
|
UIColor *fillColor = [[UIColor greenColor] colorWithAlphaComponent:0.4];
|
||||||
|
|
||||||
|
ASImageNode *debugOverlay = [self debugHighlightOverlay];
|
||||||
|
|
||||||
|
// determine if edges are clipped and if so, highlight the restricted edges
|
||||||
|
if (clippedEdges == UIRectEdgeNone) {
|
||||||
|
debugOverlay.backgroundColor = fillColor;
|
||||||
|
} else {
|
||||||
|
const CGFloat borderWidth = 2.0;
|
||||||
|
UIColor *borderColor = [[UIColor orangeColor] colorWithAlphaComponent:0.8];
|
||||||
|
UIColor *clipsBorderColor = [UIColor colorWithRed:30/255.0 green:90/255.0 blue:50/255.0 alpha:0.7];
|
||||||
|
CGRect imgRect = CGRectMake(0, 0, 2.0 * borderWidth + 1.0, 2.0 * borderWidth + 1.0);
|
||||||
|
|
||||||
|
UIGraphicsBeginImageContext(imgRect.size);
|
||||||
|
|
||||||
|
[fillColor setFill];
|
||||||
|
UIRectFill(imgRect);
|
||||||
|
|
||||||
|
[self drawEdgeIfClippedWithEdges:clippedEdges color:clipsBorderColor borderWidth:borderWidth imgRect:imgRect];
|
||||||
|
[self drawEdgeIfClippedWithEdges:clipsToBoundsClippedEdges color:borderColor borderWidth:borderWidth imgRect:imgRect];
|
||||||
|
|
||||||
|
UIImage *debugHighlightImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||||
|
UIGraphicsEndImageContext();
|
||||||
|
|
||||||
|
UIEdgeInsets edgeInsets = UIEdgeInsetsMake(borderWidth, borderWidth, borderWidth, borderWidth);
|
||||||
|
debugOverlay.image = [debugHighlightImage resizableImageWithCapInsets:edgeInsets resizingMode:UIImageResizingModeStretch];
|
||||||
|
debugOverlay.backgroundColor = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
debugOverlay.frame = finalRect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIRectEdge)setEdgesOfIntersectionForChildRect:(CGRect)childRect parentRect:(CGRect)parentRect rectEdge:(UIRectEdge)rectEdge
|
||||||
|
{
|
||||||
|
// determine which edges of childRect are outside parentRect (and thus will be clipped)
|
||||||
|
if (childRect.origin.y < parentRect.origin.y) {
|
||||||
|
rectEdge |= UIRectEdgeTop;
|
||||||
|
}
|
||||||
|
if (childRect.origin.x < parentRect.origin.x) {
|
||||||
|
rectEdge |= UIRectEdgeLeft;
|
||||||
|
}
|
||||||
|
if (CGRectGetMaxY(childRect) > CGRectGetMaxY(parentRect)) {
|
||||||
|
rectEdge |= UIRectEdgeBottom;
|
||||||
|
}
|
||||||
|
if (CGRectGetMaxX(childRect) > CGRectGetMaxX(parentRect)) {
|
||||||
|
rectEdge |= UIRectEdgeRight;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rectEdge;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)drawEdgeIfClippedWithEdges:(UIRectEdge)rectEdge color:(UIColor *)color borderWidth:(CGFloat)borderWidth imgRect:(CGRect)imgRect
|
||||||
|
{
|
||||||
|
[color setFill];
|
||||||
|
|
||||||
|
// highlight individual edges of overlay if edge is restricted by parentRect
|
||||||
|
// so that the developer is aware that increasing hitTestSlop will not result in an expanded tappable area
|
||||||
|
if (rectEdge & UIRectEdgeTop) {
|
||||||
|
UIRectFill(CGRectMake(0.0, 0.0, imgRect.size.width, borderWidth));
|
||||||
|
}
|
||||||
|
if (rectEdge & UIRectEdgeLeft) {
|
||||||
|
UIRectFill(CGRectMake(0.0, 0.0, borderWidth, imgRect.size.height));
|
||||||
|
}
|
||||||
|
if (rectEdge & UIRectEdgeBottom) {
|
||||||
|
UIRectFill(CGRectMake(0.0, imgRect.size.height - borderWidth, imgRect.size.width, borderWidth));
|
||||||
|
}
|
||||||
|
if (rectEdge & UIRectEdgeRight) {
|
||||||
|
UIRectFill(CGRectMake(imgRect.size.width - borderWidth, 0.0, borderWidth, imgRect.size.height));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|||||||
Reference in New Issue
Block a user