diff --git a/Coach Marks/DDBubble.m b/Coach Marks/DDBubble.m index 4a9867e..adfe343 100755 --- a/Coach Marks/DDBubble.m +++ b/Coach Marks/DDBubble.m @@ -55,14 +55,18 @@ -(id)initWithFrame:(CGRect)frame title:(NSString*)title description:(NSString*)d [self setFrame:[self calculateFrameWithFont:font]]; [self fixFrameIfOutOfBounds]; + // Make it pass touch events through to the DDCoachMarksView + [self setUserInteractionEnabled:NO]; + // calculate and position text CGSize offsets = [self offsets]; float actualXPosition = offsets.width+PADDING*1.5; float actualYPosition = offsets.height+PADDING*1.25; - float actualWidth = self.frame.size.width-offsets.width-PADDING*3; - float actualHeight = self.frame.size.height-offsets.height-PADDING*2.5; + float actualWidth = self.frame.size.width-actualXPosition - PADDING*1.5; + float actualHeight = self.frame.size.height - actualYPosition - PADDING*1.2; UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(actualXPosition, actualYPosition, actualWidth, actualHeight)]; + [titleLabel setFont:font]; [titleLabel setTextColor:TEXT_COLOR]; [titleLabel setAlpha:0.9]; [titleLabel setFont:font]; @@ -70,9 +74,9 @@ -(id)initWithFrame:(CGRect)frame title:(NSString*)title description:(NSString*)d [titleLabel setBackgroundColor:[UIColor clearColor]]; [titleLabel setLineBreakMode:NSLineBreakByWordWrapping]; [titleLabel setNumberOfLines:0]; + [titleLabel setUserInteractionEnabled:NO]; [self addSubview:titleLabel]; - [self setNeedsDisplay]; return self; } @@ -95,7 +99,7 @@ - (void)fixFrameIfOutOfBounds CGRect window = [[[UIApplication sharedApplication] keyWindow] frame]; const float xBounds = window.size.width; // 320; -// const float yBounds = 568; + const float yBounds = window.size.height; float x = self.frame.origin.x; float y = self.frame.origin.y; @@ -111,10 +115,30 @@ - (void)fixFrameIfOutOfBounds } // check for left most bound if (x < 0) { - _arrowOffset = x - padding; + if (_arrowOffset == 0) { + _arrowOffset = x - padding; + } x = 0; } + // If the content pushes us off the vertical bounds we might have to be more drastic + // and flip the arrow direction + if ((self.arrowPosition == CRArrowPositionTop) && (y + height > yBounds)) { + self.arrowPosition = CRArrowPositionBottom; + + // Restart the entire process + CGRect flippedFrame = [self calculateFrameWithFont:[self font]]; + y = flippedFrame.origin.y; + height = flippedFrame.size.height; + } else if ((self.arrowPosition == CRArrowPositionBottom) && (y < 0)) { + self.arrowPosition = CRArrowPositionTop; + + // Restart the entire process + CGRect flippedFrame = [self calculateFrameWithFont:[self font]]; + y = flippedFrame.origin.y; + height = flippedFrame.size.height; + } + [self setFrame:CGRectMake(x, y, width, height)]; } @@ -126,29 +150,38 @@ -(CGRect)calculateFrameWithFont:(UIFont*)font CGSize size = [self sizeWithFont:font]; + float widthDelta = 0, heightDelta = 0; + if(self.arrowPosition==CRArrowPositionLeft||self.arrowPosition==CRArrowPositionRight) { y+=self.attachedFrame.size.height/2-size.height/2; x+=(self.arrowPosition==CRArrowPositionLeft)? ARROW_SPACE+self.attachedFrame.size.width : -(ARROW_SPACE*2+size.width); + widthDelta = ARROW_SIZE; }else if(self.arrowPosition==CRArrowPositionTop||self.arrowPosition==CRArrowPositionBottom) { x+=self.attachedFrame.size.width/2-size.width/2; y+=(self.arrowPosition==CRArrowPositionTop)? ARROW_SPACE+self.attachedFrame.size.height : -(ARROW_SPACE*2+size.height); + heightDelta = ARROW_SIZE; } - CGSize offsets = [self offsets]; - return CGRectMake(x, y, size.width+offsets.width, size.height+offsets.height); + return CGRectMake(x, y, size.width+widthDelta, size.height+heightDelta); } -(CGSize)sizeWithFont:(UIFont*)font { // Calcultation of the bubble size // size of bubble title determined by the strings attributes - CGSize offset = [self offsets]; CGRect window = [[[UIApplication sharedApplication] keyWindow] frame]; - CGSize result = [_title sizeWithFont:font constrainedToSize:CGSizeMake(window.size.width - offset.width - (PADDING*4), FLT_MAX) lineBreakMode:NSLineBreakByWordWrapping]; + float widthDelta = 0; + if(self.arrowPosition==CRArrowPositionLeft||self.arrowPosition==CRArrowPositionRight) + { + // Make space for an arrow on one side + widthDelta = ARROW_SIZE; + } + + CGSize result = [_title sizeWithFont:font constrainedToSize:CGSizeMake(window.size.width - widthDelta - (PADDING*3), FLT_MAX) lineBreakMode:NSLineBreakByWordWrapping]; return CGSizeMake(result.width + (PADDING*3), result.height + (PADDING*2.5)); } diff --git a/Coach Marks/DDCircleView.m b/Coach Marks/DDCircleView.m index b0de0e5..601ea76 100644 --- a/Coach Marks/DDCircleView.m +++ b/Coach Marks/DDCircleView.m @@ -38,7 +38,7 @@ - (void)userTap:(UITapGestureRecognizer *)recognizer { - (void)swipeInFrame:(CGRect)frame { - [self centerYPositioninView:self inFrame:frame]; + [self centerInView:self inFrame:frame]; [self animateSwipe]; } @@ -54,7 +54,7 @@ - (void)animateSwipe self.transform = CGAffineTransformConcat(translateRight, scale); } self.alpha = 0.0f; - [UIView animateKeyframesWithDuration:0.6 delay:0.3 options:0 + [UIView animateWithDuration:0.6 delay:0.3 options:0 animations:^{ // Fade In if (self.swipeDirection == kCircleSwipeLeftToRight) { @@ -101,7 +101,7 @@ - (void)centerYPositioninView:(UIView *)view inFrame:(CGRect)frame - (void)centerXPositioninView:(UIView *)view inFrame:(CGRect)frame { CGFloat centerX = frame.origin.x + CGRectGetWidth(frame)/2; - CGFloat offsetX = CGRectGetWidth(view.frame)/2; + CGFloat offsetX = 260/2; CGFloat newX = centerX - offsetX; view.frame = CGRectMake(newX, view.frame.origin.y, 40, 40); diff --git a/Coach Marks/DDCoachMarksView.m b/Coach Marks/DDCoachMarksView.m index e67ecd8..a44ec90 100755 --- a/Coach Marks/DDCoachMarksView.m +++ b/Coach Marks/DDCoachMarksView.m @@ -175,16 +175,16 @@ - (void)goToCoachMarkIndexed:(NSUInteger)index { // Current index markIndex = index; - - // Coach mark definition - NSDictionary *markDef = [self.coachMarks objectAtIndex:index]; - CGRect markRect = [[markDef objectForKey:@"rect"] CGRectValue]; - NSString *shape = [markDef objectForKey:@"shape"]; // Delegate (coachMarksView:willNavigateTo:atIndex:) if ([self.delegate respondsToSelector:@selector(coachMarksView:willNavigateToIndex:)]) { [self.delegate coachMarksView:self willNavigateToIndex:markIndex]; } + + // Coach mark definition + NSDictionary *markDef = [self.coachMarks objectAtIndex:index]; + CGRect markRect = [[markDef objectForKey:@"rect"] CGRectValue]; + NSString *shape = [markDef objectForKey:@"shape"]; if (self.useBubbles) { [self animateNextBubble]; @@ -230,7 +230,7 @@ - (void)showSwipeGesture // create an animating circle and animate it if (shouldAnimateSwipe) { - self.animatingCircle = [[DDCircleView alloc] initWithFrame:CGRectZero]; + self.animatingCircle = [[DDCircleView alloc] initWithFrame:self.frame]; if (![self.subviews containsObject:self.animatingCircle]) { [self addSubview:self.animatingCircle]; @@ -255,7 +255,7 @@ - (void)animateNextBubble // remove previous bubble if (self.bubble) { - [UIView animateKeyframesWithDuration:0.3 delay:0.0 options:0 + [UIView animateWithDuration:0.3 delay:0.0 options:0 animations:^{ self.bubble.alpha = 0.0; } completion:nil]; @@ -277,7 +277,7 @@ - (void)animateNextBubble [self addSubview:self.bubble]; // fade in & bounce animation - [UIView animateKeyframesWithDuration:0.8 delay:0.3 options:0 + [UIView animateWithDuration:0.8 delay:0.3 options:0 animations:^{ self.bubble.alpha = 1.0; [self.bubble animate]; @@ -297,7 +297,7 @@ - (void)cleanup { __weak DDCoachMarksView *weakSelf = self; // animate & remove from super view - [UIView animateKeyframesWithDuration:0.6 delay:0.3 options:0 + [UIView animateWithDuration:0.6 delay:0.3 options:0 animations:^{ self.alpha = 0.0f; self.animatingCircle.alpha = 0.0f;