IOS development-custom mask view (BOOT, function description) source code + resolution
IOS development-custom mask view (BOOT, function description) source code + resolution
When we use an App for the first time, we often use something like a "Newbie tutorial" to guide us on how to use the App.
However, this "new tutorial" is different from the general boot page (the boot page refers to the introduction view that pops up when the App is opened for the first time. It is static and does not need to interact with users. You can directly flip pages or skip them .) The so-called "Newbie tutorial" is to follow the prompts of the App step by step.
What are the advantages of this "Beginner tutorial?
Guides you through operations. For example, how to adjust the volume, how to set the focal length... Restrict users to fill in necessary information and complete necessary operations.
Now everyone should understand what this is. To implement this function, we generally use the mask layer effect. It took some time today to encapsulate this function. At the same time, share the source code to my Github. If you need it, you can download it by yourself.
Download link: YLZHoledView
At the same time, I also wrote a demo with the following effects:
This encapsulated file (YLZHoledView) mainly implements the following functions:
1. add multiple style spotlight effects. (Circle, rectangle, rounded rectangle, custom view)
2. Click this region to support delegate callback
3. Control event penetration in UIView. (The buttons in the demo are under the mask layer, but the correct response to the click event is the event penetration)
Well, the general introduction is here. The core code is briefly explained below:
Delegate callback
YLZHoledView.h
@class YLZHoledView;@protocol YLZHoledViewDelegate
- (void)holedView:(YLZHoledView *)holedView didSelectHoleAtIndex:(NSUInteger)index;@end
YLZHoledView.m
#pragma mark - Tap Gesture - (void)tapGestureDetectedForGesture:(UITapGestureRecognizer *)gesture { if ([self.holeViewDelegate respondsToSelector:@selector(holedView:didSelectHoleAtIndex:)]) { CGPoint touchLocation = [gesture locationInView:self]; [self.holeViewDelegate holedView:self didSelectHoleAtIndex:[self holeViewIndexForAtPoint:touchLocation]]; } }
Add a gesture in the Custom View, and then
- (NSUInteger)holeViewIndexForAtPoint:(CGPoint)touchLocation
To determine whether the click range belongs to the view added in the mask layer, and then send the delegate.
Then, in our implementation class, that is, the place where this delegate is implemented, you can use index to perform related operations. In my demo, it is just a simple print.
Spotlight Effect
I have encapsulated several common types here. (Circle, rectangle, rounded rectangle, custom view)
typedef NS_ENUM(NSInteger, YLZHoleType) { YLZHoleTypeCirle, YLZHoleTypeRect, YLZHoleTypeRoundedRect, YLZHoleTypeCustomRect };
Then rewrite
- (void)drawRect:(CGRect)rect
Rewrite the corresponding effect by determining the type.
For example, the circular code:
if (hole.holeType == YLZHoleTypeRoundedRect) { YLZRoundedRectHole *rectHole = (YLZRoundedRectHole *)hole; CGRect holeRectIntersection = CGRectIntersection( rectHole.holeRect, self.frame); UIBezierPath *bezierPath = [UIBezierPath bezierPathWithRoundedRect:holeRectIntersection cornerRadius:rectHole.holeCornerRadius]; CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), [[UIColor clearColor] CGColor]); CGContextAddPath(UIGraphicsGetCurrentContext(), bezierPath.CGPath); CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeClear); CGContextFillPath(UIGraphicsGetCurrentContext());}
Event penetration
Before that, provide a method.
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;
// Recursively cballs-pointInside: withEvent:. point is in the specified er's coordinate system
As long as the hitTest method of the top-level UIView is implemented, a lower-level button instance is returned in some cases, that is, the event of that button is revealed. For example, when you click this button, no matter how many layers of the button in the UIView can be dug out.
Therefore, rewrite the hitTest method.
#pragma mark - UIView Overrides - (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event { UIView *hitView = [super hitTest:point withEvent:event]; if (hitView == self) { for (UIView *focus in self.focusView) { if (CGRectContainsPoint(focus.frame, point)) { return focus; } } } return hitView; }