iphonemaclover iphonemaclover - 1 month ago 7
Objective-C Question

Create show Case view In Tabbar xcode

I am trying to create my own custom show case view , In which i have left button , right button and a tab bar view.

I want to highlight the buttons with round circle around it.
I am able to create a single Circle around my button by subclass UIView
But what i do so user swipe from left to right it will change the Circle to right button and the left button hide.
Here is my subclass of UIView

//--------.h class

#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


And inside my tabbar first view i call using

#import "IntroView.h"


then

- (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.
}


Here is my output

enter image description here

And expected Output on Slide right to left , and so or in reverse (like we do in showcase android library )

enter image description here

Answer

In IntroView.h

#import <UIKit/UIKit.h>

@interface IntroView : UIView
- (id)initWithFrame:(CGRect)frame introElements:(NSArray *)iElements;
- (void)showIntro;
@end

In IntroView.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;
}

In 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];
}

Note: i made a highlight to the UIControl frame, if you need a circle highlight, update the changes in the CGRect.