pop up menu with long press gesture - ios

I'm new to ios and also core animation so I'm doing some tests to get used to it.
I've got a menu I'm trying to create by doing a long press gesture. I want the button to by animating up and then animate down and then disappear. I got the appearing part working, but I can't figure out how to make it disappear. It also doesn't let me animate my imageView in my UIGestureRecognizerStateEnded statement. Basically, I have two questions:
How can I animate the button going down when the long press is released?
How can I only make one of these buttons instead of them appearing every time I do a long press?
Here's what I have in my .m
-(void)onPress:(UILongPressGestureRecognizer*)longpress{
CGPoint touchCenter = [longpress locationInView:self.view];
UIImage *plus = [UIImage imageNamed:#"plus"];
imageView = [[UIImageView alloc]initWithImage:plus];
CGRect imageViewFrame = CGRectMake(0, 0, 35, 35);
imageViewFrame.origin = CGPointMake(touchCenter.x - imageViewFrame.size.width / 2.0f, touchCenter.y - imageViewFrame.size.height / 2.0f);
imageView.frame = imageViewFrame;
if (longpress.state == UIGestureRecognizerStateBegan) {
[self.view addSubview:imageView];
[UIView animateWithDuration:0.6 animations:^{
CGAffineTransform moveTrans = CGAffineTransformMakeTranslation(0, -40);
imageView.transform = moveTrans;
}];
NSLog(#"Long press");
return;
}else{
if (longpress.state == UIGestureRecognizerStateEnded || longpress.state == UIGestureRecognizerStateCancelled || longpress.state == UIGestureRecognizerStateFailed) {
[UIView animateWithDuration:0.6 animations:^{
CGAffineTransform moveTrans = CGAffineTransformMakeTranslation(0, 40);
imageView.transform = moveTrans;
NSLog(#"long press done");
}];
}
}
}
and my .h
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#interface ViewController : UIViewController<UIGestureRecognizerDelegate>
{
UIImageView *imageView;
CAShapeLayer *layer;
}
#property(nonatomic) float angle;
#property(nonatomic, strong) UIImageView *imageView;
#property (nonatomic, strong) UIImage *image;
#end

I'm now sure what you want to do. But I modified some of your code:
#interface ViewController ()
#property (strong, nonatomic) UIView *moveView;
#end
- (void)viewDidLoad
{
[super viewDidLoad];
UILongPressGestureRecognizer *recoginzer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(onPress:)];
[self.view addGestureRecognizer:recoginzer];
}
- (void)onPress:(UILongPressGestureRecognizer*)longpress {
CGPoint location = [longpress locationInView:self.view];
if (longpress.state == UIGestureRecognizerStateBegan) {
if (!self.moveView) {
self.moveView = [[UIView alloc] initWithFrame:CGRectMake(location.x, location.y, 100, 100)];
self.moveView.backgroundColor = [UIColor redColor];
[self.view addSubview:self.moveView];
} else {
self.moveView.frame = CGRectMake(location.x, location.y, 100, 100);
}
[UIView animateWithDuration:0.6 animations:^{
CGAffineTransform moveTrans = CGAffineTransformMakeTranslation(0, -40);
self.moveView.transform = moveTrans;
}];
NSLog(#"Long press");
} else if (longpress.state == UIGestureRecognizerStateEnded || longpress.state == UIGestureRecognizerStateCancelled || longpress.state == UIGestureRecognizerStateFailed) {
[UIView animateWithDuration:0.6 animations:^{
CGAffineTransform moveTrans = CGAffineTransformMakeTranslation(0, 40);
self.moveView.transform = moveTrans;
NSLog(#"long press done");
}];
}
}
Let me know if you need more help.

Related

How to slide a button from the bottom after sliding from the edge?

I have implemented the following two methods
-(void)addGestureToWebView {
[self setBottomEdgeGesture:[[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:#selector(handleBottomEdgeGesture:)]];
[[self bottomEdgeGesture] setEdges:UIRectEdgeBottom];
[[self bottomEdgeGesture] setDelegate:self];
[[self webView] addGestureRecognizer:[self bottomEdgeGesture]];
}
and
-(IBAction)handleBottomEdgeGesture:(UIScreenEdgePanGestureRecognizer *)gesture {
if(UIGestureRecognizerStateBegan == [gesture state] || UIGestureRecognizerStateChanged == [gesture state]) {
//Do something
}
}
The method handleBottomEdgeGesture should slide a button with three dots from the bottom.
I tried
UIButton *btnDots = [[UIButton alloc] initWithFrame:CGRectMake(280.0, 528.0, 20, 20)];
[btnDots setTitle:#"..." forState:UIControlStateNormal];
[btnDots setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
but nothing happened. I didn't see any dots at my display. I am new to Objective-C and some things not so easy to develop.
Can anyone give me a good advice?
Since you created a button programmatically you also need to add it to sub view. Then on gesture recognizer you should change the frame of the button. A reference to the button will be needed.
Lets say you are doing this in the view controller. Create a property for dot button. In view did load create the button and assign it to the property:
UIButton *dotButton = [[UIButton alloc] initWithFrame:CGRectMake(.0f, self.view.frame.size.height, self.view.frame.size.width, 20.0f)];
// do additional button setup
[self.view addSubview:dotButton];
[dotButton addTarget:self action:#selector(onDotButtonPressed) forControlEvents:UIControlEventTouchUpInside];
self.dotButton = dotButton;
Then in gesture recognizer you have 2 options. Either just handle the event and show the button animated or move its frame as your finger moves:
- (void)onGesture:(UIGestureRecognizer *)sender
{
#ifdef USE_ONLY_ON_EVENT
if(sender.state == UIGestureRecognizerStateBegan)
{
[UIView animateWithDuration:.23 animations:^{
self.dotButton.frame = CGRectMake(.0f, self.view.frame.size.height-self.dotButton.frame.size.height, self.view.frame.size.width, self.dotButton.frame.size.height);
}];
}
#else
if(sender.state == UIGestureRecognizerStateBegan || sender.state == UIGestureRecognizerStateChanged)
{
CGPoint location = [sender locationInView:self.view];
CGFloat yOffset = self.view.frame.size.height - location.y;
if(yOffset > self.dotButton.frame.size.height)
{
yOffset = self.dotButton.frame.size.height;
}
self.dotButton.frame = CGRectMake(.0f, self.view.frame.size.height-yOffset, self.view.frame.size.width, self.dotButton.frame.size.height);
}
else if(sender.state == UIGestureRecognizerStateEnded || sender.state == UIGestureRecognizerStateCancelled)
{
CGPoint location = [sender locationInView:self.view];
CGFloat yOffset = self.view.frame.size.height - location.y;
if(yOffset > self.dotButton.frame.size.height*.5f) // more then half of a button visible
{
// show full button
[UIView animateWithDuration:.23 animations:^{
self.dotButton.frame = CGRectMake(.0f, self.view.frame.size.height-self.dotButton.frame.size.height, self.view.frame.size.width, self.dotButton.frame.size.height);
}];
}
else
{
// hide button
[UIView animateWithDuration:.23 animations:^{
self.dotButton.frame = CGRectMake(.0f, self.view.frame.size.height, self.view.frame.size.width, self.dotButton.frame.size.height);
}];
}
}
#endif
}
I hope you get the basic idea from the code.

Bug Transition Animation ViewControllers

I have a simple interactive animation : the same as the iOS transition between pages. But when the transition is finished or cancelled, sometimes, it go back to an old position, like a back effect. Here's my code, you can test it to see what i mean. How can I fix it ? Also, does a better method exist to make an interactive transition between ViewControllers ?
Thx
NavigationControllerDelegate.m
#import "NavigationControllerDelegate.h"
#import "Animator.h"
#interface NavigationControllerDelegate ()
#property (weak, nonatomic) IBOutlet UINavigationController *navigationController;
#property (strong, nonatomic) Animator* animator;
#property (strong, nonatomic) UIPercentDrivenInteractiveTransition* interactionController;
#end
#implementation NavigationControllerDelegate
- (void)awakeFromNib
{
UIPanGestureRecognizer* panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(pan:)];
[self.navigationController.view addGestureRecognizer:panRecognizer];
self.animator = [Animator new];
}
- (void)pan:(UIPanGestureRecognizer*)recognizer
{
UIView* view = self.navigationController.view;
if (recognizer.state == UIGestureRecognizerStateBegan) {
CGPoint location = [recognizer locationInView:view];
if (location.x < CGRectGetMidX(view.bounds) && self.navigationController.viewControllers.count > 1) { // left half
self.interactionController = [UIPercentDrivenInteractiveTransition new];
[self.navigationController popViewControllerAnimated:YES];
}
} else if (recognizer.state == UIGestureRecognizerStateChanged) {
CGPoint translation = [recognizer translationInView:view];
CGFloat d = fabs(translation.x / CGRectGetWidth(view.bounds));
[self.interactionController updateInteractiveTransition:d];
} else if (recognizer.state == UIGestureRecognizerStateEnded) {
CGPoint translation = [recognizer translationInView:view];
CGFloat d = (translation.x / CGRectGetWidth(view.bounds));
if (d > 0.5) {
[self.interactionController finishInteractiveTransition];
} else {
[self.interactionController cancelInteractiveTransition];
}
self.interactionController = nil;
}
}
- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC
{
if (operation == UINavigationControllerOperationPop) {
return self.animator;
}
return nil;
}
- (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController
{
return self.interactionController;
}
#end
Animator.m
#import "Animator.h"
#implementation Animator
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
{
return 1;
}
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
{
CGRect screenBounds = [[UIScreen mainScreen] bounds];
UIViewController* toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
UIViewController* fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
[[transitionContext containerView] addSubview:toViewController.view];
toViewController.view.frame = CGRectMake(-screenBounds.size.width, 0, screenBounds.size.width, screenBounds.size.height);
[UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{
toViewController.view.frame = CGRectMake(0, 0, screenBounds.size.width, screenBounds.size.height);
fromViewController.view.frame = CGRectMake(screenBounds.size.width, 0, screenBounds.size.width, screenBounds.size.height);
} completion:^(BOOL finished) {
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
}];
}
#end

UITapGestureRecognizer not responding on animated subview

I have a simple program that creates a subview and animates it across the screen.
As part of this program, I would like to add functionality when the subview is tapped. I am using the following method to create the subview, add the UITapGestureRecognizer and then animate the subview:
int randomName = arc4random() % ([pieceNames count] - 1);
int animationDuration = arc4random() % 5 + 5 ;
NSString *randomPiece = [pieceNames objectAtIndex:randomName];
float yStart = arc4random() % 650;
float yEnd = arc4random() % 650;
UIView *piece = [[PieceView alloc]initWithFrame:CGRectMake(100.0, yStart, 75.0, 75.0)];
[piece setValue:randomPiece forKey:#"name"];
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc]initWithTarget:self
action:#selector(handleTouch:)];
[piece addGestureRecognizer:recognizer];
[[self view] addSubview:piece];
[UIView animateWithDuration:animationDuration
delay:0.0
options:UIViewAnimationOptionAllowUserInteraction
animations:^(void){
piece.center = CGPointMake(950.0, yEnd);
} completion:^(BOOL done){
[piece removeFromSuperview];
}];
Here is the code that handles the tap:
PieceView *pv = (PieceView *) recognizer.view;
NSLog(#"%# was tapped", pv.name);
What happens is when a PieceView is touched the program does not respond. However, if I remove the animation block then the program responds to the tap.
Why does the UITapGestureRecognizer fail to respond to PieceView when it is animated?
I struggled with this same problem, and it boils down to this: the animated view only ever is in two places: the starting position, and the ending position. Core Animation simply renders the view's layer in interpolated positions between the start and end points over a period of time.
It's almost like when you look to the stars and realize that what you see is not actually what is happening right now. :)
Luckily, the solution is pretty simple. You can put a tap recognizer on the superview and then inspect your animated view's presentationLayer (which does give you an accurate frame at any point in time) to determine if your tap is a hit or not.
I've built a simple UIViewController that demonstrates both the problem and solution:
#import <UIKit/UIKit.h>
#interface MSMViewController : UIViewController
#end
And the implementation:
#import "MSMViewController.h"
#interface MSMViewController ()
#property (nonatomic, strong) UIView *animatedView;
#end
#implementation MSMViewController
- (void)viewDidLoad {
[super viewDidLoad];
CGRect startFrame = CGRectMake(125, 0, 70, 70);
CGRect endFrame = CGRectMake(125, 400, 70, 70);
// draw a box to show where the animated view begins
UIView *startOutlineView = [[UIView alloc] initWithFrame:startFrame];
startOutlineView.layer.borderColor = [UIColor blueColor].CGColor;
startOutlineView.layer.borderWidth = 1;
[self.view addSubview:startOutlineView];
// draw a box to show where the animated view ends
UIView *endOutlineView = [[UIView alloc] initWithFrame:endFrame];
endOutlineView.layer.borderColor = [UIColor blueColor].CGColor;
endOutlineView.layer.borderWidth = 1;
[self.view addSubview:endOutlineView];
self.animatedView = [[UIView alloc] initWithFrame:startFrame];
self.animatedView.backgroundColor = [UIColor yellowColor];
[self.view addSubview:self.animatedView];
[UIView animateWithDuration:10 delay:2 options:UIViewAnimationOptionAllowUserInteraction animations:^{
self.animatedView.frame = endFrame;
} completion:nil];
// this gesture recognizer will only work in the space where endOutlintView is
UITapGestureRecognizer *boxTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(boxTap:)];
[self.animatedView addGestureRecognizer:boxTap];
// this one will work
UITapGestureRecognizer *superviewTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(superviewTap:)];
[self.view addGestureRecognizer:superviewTap];
}
- (void)boxTap:(UITapGestureRecognizer *)tap {
NSLog(#"tap. view is at %#", NSStringFromCGPoint(self.animatedView.frame.origin));
}
- (void)superviewTap:(UITapGestureRecognizer *)tap {
CGRect boxFrame = [self.animatedView.layer.presentationLayer frame];
if (CGRectContainsPoint(boxFrame, [tap locationInView:self.view])) {
NSLog(#"we tapped the box!");
}
}
#end
The solution is much simpler, you just need to set the animation's option UIViewAnimationOptions.allowUserInteraction.
UIView.animate(withDuration: duration, delay: 0.1, options: [.allowUserInteraction], animations: {
...
}, completion: { (completed) in
...
}

IOS: make running text as "running news line in TV"?

I'm interesting, how can it is possible to make text moving from right to left like a "running news line in TV"?
I can do text moving from right to left (or any other) in UILabel, but this animation moving should be infinity loop, not only one time.
Here's a few:
https://github.com/caydenliew/CLTickerView
https://github.com/malcommac/DMScrollingTicker
https://github.com/MugunthKumar/MKTickerViewDemo
https://github.com/jeffhodnett/JHTickerView
https://github.com/cbess/AutoScrollLabel
There's probably more at Cocoa Controls.
How about like this:
-(void) animate {
label.center = CGPointMake(self.view.bounds.size.width + label.bounds.size.width/2, label.center.y);
[UIView animateWithDuration:20 delay:0 options:(UIViewAnimationOptionCurveLinear | UIViewAnimationOptionRepeat) animations:^{
label.center = CGPointMake(0 - label.bounds.size.width/2, label.center.y);
} completion:nil];
}
// CrawlView.h
#import <UIKit/UIKit.h>
#interface CrawlView : UIScrollView
#property (assign, nonatomic) NSTimeInterval period;
#property (strong, nonatomic) NSMutableArray *messages;
- (void)go;
#end
// CrawlView.m
#define kWORD_SPACE 16.0f
#import "CrawlView.h"
#interface CrawlView ()
#property (assign, nonatomic) CGFloat messagesWidth;
#end
#implementation CrawlView
- (void)buildSubviews {
for (UIView *subview in [self subviews]) {
if ([subview isKindOfClass:[UILabel self]]) {
[subview removeFromSuperview];
}
}
CGFloat xPos = kWORD_SPACE;
for (NSString *message in self.messages) {
UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
label.text = message;
CGSize size = [message sizeWithFont:label.font];
CGFloat width = size.width + kWORD_SPACE;
label.frame = CGRectMake(xPos, 0.0, width, self.frame.size.height);
[self addSubview:label];
xPos += width;
}
self.messagesWidth = xPos;
self.contentSize = CGSizeMake(xPos, self.frame.size.height);
self.contentOffset = CGPointMake(-self.frame.size.width, 0.0);
}
- (void)go {
[self buildSubviews];
if (!self.period) self.period = self.messagesWidth / 100;
[UIView animateWithDuration:self.period
delay:0.0
options:UIViewAnimationOptionCurveLinear |UIViewAnimationOptionRepeat
animations:^{
self.contentOffset = CGPointMake(self.messagesWidth, 0.0);
} completion:^(BOOL finished){
[self buildSubviews];}];
}
#end

CustomAnnotationView with a button

I've been strunggling with an issue on my project :
I've a mapView and I have to show the annotation presented below (The small (+) is my button)
I've subclassed MKAnnotationView and I have CustomAnnotationView.h like this :
#interface CustomAnnotationView : MKAnnotationView
#property (strong, nonatomic) UIImageView *calloutView;
#property (strong, nonatomic) UIButton *pinButton;
#property (strong, nonatomic) UIView *annView;
- (void)setSelected:(BOOL)selected animated:(BOOL)animated;
- (void)animateCalloutAppearance;
My CustomAnnotationView.m
- (void)setSelected:(BOOL)selected animated:(BOOL)animated{
[super setSelected:selected animated:animated];
if(selected)
{
//building my custom animation
annView = [[ UIView alloc ] initWithFrame:(CGRectMake(0, 0, 30, 30)) ];
annView.frame =CGRectMake(0, 0, 200, 50);
calloutView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"customcallout.png"]];
[calloutView setFrame:CGRectMake(-25, 50, 0, 0)];
[calloutView sizeToFit];
[self animateCalloutAppearance];
//I tried to add a button here but I could't do it like it should be
[annView addSubview:calloutView];
[self addSubview:annView];
}
else
{
//Remove your custom view...
[annView removeFromSuperview];
}
}
- (void)didAddSubview:(UIView *)subview{
if ([[[subview class] description] isEqualToString:#"UICalloutView"]) {
for (UIView *subsubView in subview.subviews) {
if ([subsubView class] == [UIImageView class]) {
UIImageView *imageView = ((UIImageView *)subsubView);
[imageView removeFromSuperview];
}else if ([subsubView class] == [UILabel class]) {
UILabel *labelView = ((UILabel *)subsubView);
[labelView removeFromSuperview];
}
}
}
}
- (void)animateCalloutAppearance {
CGFloat scale = 0.001f;
calloutView.transform = CGAffineTransformMake(scale, 0.0f, 0.0f, scale, 0, -50);
[UIView animateWithDuration:0.15 delay:0 options:UIViewAnimationCurveEaseOut animations:^{
CGFloat scale = 1.1f;
calloutView.transform = CGAffineTransformMake(scale, 0.0f, 0.0f, scale, 0, 2);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.1 delay:0 options:UIViewAnimationCurveEaseInOut animations:^{
CGFloat scale = 0.95;
calloutView.transform = CGAffineTransformMake(scale, 0.0f, 0.0f, scale, 0, -2);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.075 delay:0 options:UIViewAnimationCurveEaseInOut animations:^{
CGFloat scale = 1.0;
calloutView.transform = CGAffineTransformMake(scale, 0.0f, 0.0f, scale, 0, 0);
} completion:nil];
}];
}];
}
#end
With this I'm able to show my custom annotation on the map but I can't figure out how to place a button on it and this button should of course be able to respond to clicks like the callback calloutAccessoryControlTapped:
Please anyone with a working example code or idea.
Thank you.
I solved this using - (UIView*)hitTest in my CustmAnnotationView.m class. I have a separate nib for the callout view and use hittest to determine whether the UILabel named directionsButton (linked from the callout nib) was clicked:
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
if (selected) {
calloutVisible = YES;
hitTestBuffer = NO;
self.calloutView = [[[NSBundle mainBundle] loadNibNamed:#"CalloutView" owner:self options:nil] objectAtIndex:0];
[directionsButton setFont:[UIFont fontWithName:#"DIN-Medium" size:12.0f]];
[calloutView setFrame:CGRectMake(calloutView.frame.origin.x, calloutView.frame.origin.y, 280, calloutView.frame.size.height)];
[calloutView setAlpha:0.0f];
[self addSubview:calloutView];
[self sendSubviewToBack:calloutView];
[UIView animateWithDuration:0.3f delay:0.0f options:0 animations:^{
[calloutView setAlpha:1.0f];
} completion:^(BOOL finished) {
}];
[super setSelected:selected animated:animated];
} else {
calloutVisible = NO;
CGRect newFrame = self.frame;
newFrame.size.width = 52;
self.frame = newFrame;
[UIView animateWithDuration:0.3f delay:0.0f options:0 animations:^{
[calloutView setAlpha:0.0f];
} completion:^(BOOL finished) {
[calloutView removeFromSuperview];
}];
}
}
- (void)directionsPressed
{
if ([parent respondsToSelector:#selector(directionsPressed:)])
[parent performSelector:#selector(directionsPressed:) withObject:self.stockist];
}
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
if (calloutVisible) {
CGPoint hitPoint = [calloutView convertPoint:point toView:directionsButton];
if ([calloutView pointInside:hitPoint withEvent:event]) {
if (!hitTestBuffer) {
[self directionsPressed];
hitTestBuffer = YES;
}
return [directionsButton hitTest:point withEvent:event];
} else {
hitTestBuffer = NO;
}
}
return [super hitTest:point withEvent:event];
}
In my code parent is my current VC. This is probably not the neatest way but it worked at the time.
The callout looks like this:
A couple of booleans calloutVisible and hitTestBuffer make sure the button is only clickable once and only when visible.
To try and resolve your issue, I played a bit with Apple's WeatherMap example, and came up with a working solution to your problem.
I added your code to the WeatherAnnotationView.m file (minus the animation code), and on top of that added the code to display the button, and respond to touch events:
-(void)annotationButtonClicked{
NSLog(#"** button clicked");
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated{
if(selected)
{
//building my custom animation
annView = [[ UIView alloc ] initWithFrame:(CGRectMake(0, 0, 30, 30)) ];
annView.frame =CGRectMake(0, 0, 200, 50);
calloutView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"cloudy.png"]];
[calloutView setFrame:CGRectMake(-25, 50, 0, 0)];
[calloutView sizeToFit];
[annView addSubview:calloutView];
/* BUTTON CODE */
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0,0,20,20)];
button.backgroundColor = [UIColor orangeColor];
[button addTarget:self action:#selector(annotationButtonClicked) forControlEvents:UIControlEventTouchUpInside];
[annView addSubview:button];
/* END Of BUTTON CODE */
[self addSubview:annView];
}
else
{
//Remove your custom view...
[annView removeFromSuperview];
}
}
You haven't posted HOW you tried to add a button to the annView, so it is hard for me to understand what was not working with your approach. A common approach for these kind of problems is to remove one piece of code at a time and try to run your app. For starters, try to remove the animation code. Then, try to remove calloutView, and remain only with annView and the button, until you have code that works with a button. After that, add back the pieces you removed earlier (animation, calloutView) one at a time and see which one is causing your button to stop function.
I hope this helps somehow.

Resources