#ios #objective-c #xcode #uiview
#iOS #objective-c #xcode #uiview
Вопрос:
Я пытаюсь создать свой собственный пользовательский вид витрины, в котором у меня есть левая кнопка, правая кнопка и вид панели вкладок.
Я хочу выделить кнопки круглым кружком вокруг них. Я могу создать один круг вокруг моей кнопки с помощью подкласса UIView, но то, что я делаю, чтобы пользователь провел пальцем слева направо, изменит круг на правую кнопку, а левую кнопку скроет. Вот мой подкласс UIView
//———. h класс
#import <UIKit/UIKit.h>
@interface IntroView : UIView
- (void)drawRect:(CGRect)rect withBtnRect:(CGRect)btnrect ;
@end
//——. m class
#import "IntroView.h"
@implementation IntroView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
self.backgroundColor= [[UIColor blackColor] colorWithAlphaComponent:0.3];
return self;
}
- (void)drawRect:(CGRect)rect {
CGRect maskRect= CGRectMake(5, 5, 100, 100);//set and pass this maskRect
CGRect rBounds = self.bounds;
CGContextRef context = UIGraphicsGetCurrentContext();
// Fill background with 40% gray
CGContextSetFillColorWithColor(context, [[[UIColor grayColor] colorWithAlphaComponent:0.4] CGColor]);
CGContextFillRect(context, rBounds);
// Draw the window 'frame'
CGContextSetStrokeColorWithColor(context, [[UIColor whiteColor] CGColor]);
CGContextSetLineWidth(context,2);
CGContextStrokeEllipseInRect(context, maskRect);
// make the window transparent
CGContextSetBlendMode(context, kCGBlendModeClear);
CGContextFillEllipseInRect (context, maskRect);
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
@end
И внутри моего первого представления на панели вкладок я вызываю с помощью
#import "IntroView.h"
затем
- (void)viewDidLoad
{
IntroView *vw_intro=[[IntroView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];
vw_intro.tag=1000;
[self.view addSubview:vw_intro];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
Вот мой вывод
И ожидаемый результат на слайде справа налево, и так или наоборот (как мы делаем в библиотеке showcase Android)
Ответ №1:
Во внутреннем просмотре.h
#import <UIKit/UIKit.h>
@interface IntroView : UIView
- (id)initWithFrame:(CGRect)frame introElements:(NSArray *)iElements;
- (void)showIntro;
@end
Во внутреннем просмотре.m
#import "IntroView.h"
@implementation IntroView
{
CAShapeLayer *mask;
NSArray *introElements;
NSUInteger currentIndex;
}
- (id)initWithFrame:(CGRect)frame introElements:(NSArray *)iElements
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
introElements = iElements;
mask = [CAShapeLayer layer];
[mask setFillColor:[[UIColor grayColor] colorWithAlphaComponent:0.8f].CGColor];
[mask setFillRule:kCAFillRuleEvenOdd];
[self.layer addSublayer:mask];
UISwipeGestureRecognizer *swipeGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(userDidSwipe)];
swipeGestureRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
[self addGestureRecognizer:swipeGestureRecognizer];
}
return self;
}
- (void)userDidSwipe
{
[self showIntroAtIndex:currentIndex 1];
}
- (void)showIntro
{
//Initial index by default
[self showIntroAtIndex:0];
}
- (void)showIntroAtIndex:(NSUInteger)index
{
currentIndex = index;
CGRect rect = [[introElements objectAtIndex:index] CGRectValue];
UIBezierPath *maskPath = [UIBezierPath bezierPathWithRect:self.bounds];
UIBezierPath *elementPath = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:3.0f];
[maskPath appendPath:elementPath];
// Animate
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"path"];
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
animation.duration = 0.3f;
animation.fromValue = (__bridge id)(mask.path);
animation.toValue = (__bridge id)(maskPath.CGPath);
[mask addAnimation:animation forKey:@"path"];
mask.path = maskPath.CGPath;
}
В ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSArray *viewElements = [NSArray arrayWithObjects:[NSValue valueWithCGRect:button1.frame],[NSValue valueWithCGRect:button2.frame], nil];
IntroView *introView = [[IntroView alloc]initWithFrame:self.view.bounds introElements:viewElements];
[self.view addSubview:introView];
[introView showIntro];
}
Примечание: я выделил рамку UIControl, если вам нужно выделить круг, обновите изменения в CGRect.
Комментарии:
1. спасибо за красивый и быстрый ответ, я скоро преобразоваю его в circle и опубликую