View is not set back to original position - ios

In my xib i have set one text box ...when user edit in it i am moving that view little up...but when i return back it to its original postion it not come to its original postion it remain little up then original postion.
Here is viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
if ([self respondsToSelector:#selector(edgesForExtendedLayout)])self.edgesForExtendedLayout = UIRectEdgeNone;
search=FALSE;
UIButton *btnOther = [UIButton buttonWithType:UIButtonTypeSystem]; //UIButtonTypeCustom for image button
[btnOther setTitle:#"Save" forState:UIControlStateNormal];
btnOther.titleLabel.font = [UIFont fontWithName:GZFont size:12.0f];
// [btnSave setImage:[UIImage imageNamed:#"save.png"] forState:UIControlStateNormal];
[btnOther addTarget:self action:#selector(btnSaveAction:) forControlEvents:UIControlEventTouchUpInside];
[btnOther setFrame:CGRectMake(0, 0, 55, 29)];
dataArray=[[NSMutableArray alloc]init];
nameSearchArray=[[NSMutableArray alloc]init];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:btnOther];
txtCharityName.hidden=YES;
txtCharityMail.hidden=YES;
originalCenter=self.view.center;
}
here is textfield delegate methods.:
- (void)textFieldDidBeginEditing:(UITextField *)textField {
if(textField==txtGratuity){
self.view.center=CGPointMake(originalCenter.x, originalCenter.y-30);
}
}
- (void)textFieldDidEndEditing:(UITextField *)textField {
self.view.center=CGPointMake(originalCenter.x, originalCenter.y);
charityId=#"";
NSLog(#"charityID%#",charityId);
}
and here is screenshot.:

as per this equation
frame.origin = center - (bounds.size / 2.0)
center = frame.origin + (bounds.size / 2.0)
you should add 30 points for textfield to get to correct position.
- (void)textFieldDidEndEditing:(UITextField *)textField {
self.view.center=CGPointMake(originalCenter.x, originalCenter.y+30);
charityId=#"";
NSLog(#"charityID%#",charityId);
}
Edit:
try this in your
- (void)textFieldDidBeginEditing:(UITextField *)textField {
[UIView animateWithDuration:0.25
delay:0.0
options: UIViewAnimationOptionCurveEaseInOut
animations:^{
CGRect frame;
// let's move our textField
frame = textField.frame;
frame.origin.y = frame.origin.y-30;
textField.frame=frame;
}
completion:^(BOOL finished){
if(finished) NSLog(#"Finished !!!!!);
}];
}
and move textfield down after edit
- (void)textFieldDidEndEditing:(UITextField *)textField {
[UIView animateWithDuration:0.25
delay:0.0
options: UIViewAnimationOptionCurveEaseInOut
animations:^{
CGRect frame;
// let's move our textField
frame = textField.frame;
frame.origin.y = frame.origin.y+30;
textField.frame=frame;
}
completion:^(BOOL finished){
if(finished) NSLog(#"Finished !!!!!);
}];
}

Set the textfield frames in viewWillAppear instead of viewDidLoad method.

Related

Animating a UITextview in a UIToolbar issue

I am trying to animate a UITextView to expand the to the width of its containing UIToolbar.
But it animates weird, jumping around.
Can anyone help me make understand why my textbox jumps around?
#define ANIMATION_DURATION 0.5
#define ANIMATION_DELAY 0.03
#interface WebViewController () <UITextFieldDelegate>{
CGRect URLBAR_DEFAULT;
}
-(void)viewDidLoad{
self.txtURLBar = [[UITextField alloc] init];
self.txtURLBar.bounds = CGRectMake(0, 0, 100, 30);
self.txtURLBar.delegate = self;
self.txtURLBar.backgroundColor = [UIColor lightGrayColor];
self.txtURLBar.clearButtonMode = UITextFieldViewModeWhileEditing;
URLBAR_DEFAULT = self.txtURLBar.frame; //KEEP A REFRENCE TO THE ORIGINAL SIZE
}
//START EDITING EXPAND TO FULL WIDTH
- (void)textFieldDidBeginEditing:(UITextField *)textField {
[UIView animateWithDuration:ANIMATION_DURATION delay:ANIMATION_DELAY options:UIViewAnimationOptionCurveLinear animations:^{
[_txtURLBar setFrame:CGRectMake(3, URLBAR_DEFAULT.origin.y, self.view.frame.size.width - 10, URLBAR_DEFAULT.size.height)];
} completion:^(BOOL finished) {
}];
}
//END EDITING SHRINK BACK TO SMALL SIZE
- (void)textFieldDidEndEditing:(UITextField *)textField {
[UIView animateWithDuration:ANIMATION_DURATION delay:ANIMATION_DELAY options:UIViewAnimationOptionCurveEaseOut animations:^{
[_txtURLBar setFrame:CGRectMake(URLBAR_DEFAULT.origin.x, URLBAR_DEFAULT.origin.y, URLBAR_DEFAULT.size.width, URLBAR_DEFAULT.size.height)];
} completion:^(BOOL finished) {
}];
}
The problem may be due to the frame being set in textFieldDidBeginEditing, textFieldDidEndEditing is different. I've done the small POC with same code of yours as below. It's working fine.
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UITextField *resizeableTextField;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//START EDITING EXPAND TO FULL WIDTH
- (void)textFieldDidBeginEditing:(UITextField *)textField {
[UIView animateWithDuration:0.5 delay:0.03 options:UIViewAnimationOptionCurveLinear animations:^{
self.resizeableTextField.frame = CGRectMake(CGRectGetMinX(self.resizeableTextField.frame), CGRectGetMinY(self.resizeableTextField.frame), self.resizeableTextField.frame.size.width + 40, CGRectGetHeight(self.resizeableTextField.frame));
} completion:^(BOOL finished) {
}];
}
//END EDITING SHRINK BACK TO SMALL SIZE
- (void)textFieldDidEndEditing:(UITextField *)textField {
[UIView animateWithDuration:0.5 delay:0.03 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.resizeableTextField.frame = CGRectMake(CGRectGetMinX(self.resizeableTextField.frame), CGRectGetMinY(self.resizeableTextField.frame), self.resizeableTextField.frame.size.width - 40, CGRectGetHeight(self.resizeableTextField.frame));
} completion:^(BOOL finished) {
}];
}
#end

iOS keyboard animation conflict

I am currently writing an iOS app and encountered some animation issue. The following is the test code to show my question. It's just a very simple animation that lets the textField to move up when the keyboard shows and move down when the keyboard hides. Interestingly, if it is an English keyboard, it seems that the UIView animation somehow conflicts with the keyboard animation and no animations are performed, but if I switch to the Chinese keyboard, it works fine. I just want to confirm that whether it is a bug from apple....
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
UITextField *textField = [[UITextField alloc] init];
self.textField = textField;
textField.placeholder = #"Click me!!";
textField.frame = CGRectMake(100, 350, 150, 40);
[self.view addSubview:self.textField];
self.textField.delegate = self;
}
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
[UIView animateWithDuration:0.25 animations:^{
CGRect frame = self.textField.frame;
frame.origin.y -= 100;
self.textField.frame = frame;
}];
return YES;
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[self.textField resignFirstResponder];
[UIView animateWithDuration:0.25 animations:^{
CGRect frame = self.textField.frame;
frame.origin.y += 100;
self.textField.frame = frame;
}];
return YES;
}
UPDATE
It seems that it is a bug from apple... I tried to use iOS 8.3 simulator, and it works super smoothly... In iOS 9.3, if you just try showing and hiding the keyboard, even without moving the textField, the animation will get stuck after several operations...
I'd advise you to move the animation blocks to methods from the notification UIKeyboardWill{Show|Hide}Notification. The delegate methods from your text field are asking about the text field and its behavior – nothing to do with the keyboard itself (and you can even synchronize the duration, curve and delay).
You're returning YES to -textFieldShouldReturn: which is only supposed to check if the text field should process the return key tap.
From my experience with animations, sometimes everything works fine when testing with a real device. I made the suggested changes over here and everything worked fine on an iPhone 5c (iOS 8.1) and iPhone 6s Plus (iOS 10, Beta 1).
Here's a snippet of how it looks like:
- (void)viewDidLoad {
[super viewDidLoad];
[self setupNotifications];
[self initUIElements];
}
- (void)initUIElements {
CGRect frame = CGRectMake(0.f, 20.f, 200.f, 44.f);
self.textField = [[UITextField alloc] initWithFrame:frame];
self.textField.center = CGPointMake(self.view.center.x, 32.f);
self.textField.placeholder = #"Placeholder";
self.textField.delegate = self;
[self.view addSubview:self.textField];
self.imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 50.f, 50.f)];
self.imageView.center = self.view.center;
self.imageView.backgroundColor = [UIColor magentaColor];
[self.view addSubview:self.imageView];
}
- (void)setupNotifications {
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
}
- (void)keyboardWillHide:(id)sender {
[UIView animateWithDuration:1.f animations:^{
self.textField.center = CGPointMake(self.view.center.x, 32.f);
self.imageView.center = self.view.center;
}];
}
- (void)keyboardWillShow:(id)sender {
[UIView animateWithDuration:1.f animations:^{
self.textField.center = CGPointMake(self.view.center.x, 62.f);
self.imageView.center = CGPointMake(self.view.center.x, (self.view.center.y - 50.f));
}];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
[textField resignFirstResponder];
return YES;
}
#lin fu
.m
- (void)viewDidLoad {
[super viewDidLoad];
UITextField *textField = [[UITextField alloc] init];
textField.placeholder = #"Click me!!";
textField.delegate = self;
textField.frame = CGRectMake(100, 350, 150, 40);
[self.view addSubview:textField];
}
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
[UIView animateWithDuration:0.25 animations:^{
CGRect frame = textField.frame;
frame.origin.y -= 100;
textField.frame = frame;
}];
return YES;
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
[UIView animateWithDuration:0.25 animations:^{
CGRect frame = textField.frame;
frame.origin.y += 100;
textField.frame = frame;
}];
return YES;
}
in .h
Try this out. It works for me.
you have another option you can use the third party library call TPAvoidingKeyBoard it will help you out in there

TableView not animating

I want to animate UIView simultaneously. But my UIView is not animated. Side over lap But my UITableView is not animated.
[self.view addSubview:sideview];
[sidevieww setHidden:NO];
[UIView animateWithDuration:0.3 animations:^{
[sidevieww setFrame:CGRectMake(0, 0, sidevieww.frame.size.width, sidevieww.frame.size.height)];
[mytable setFrame:CGRectMake(240,mytable.frame.origin.y,mytable.frame.size.width,mytable.frame.size.height)];
[mynav setFrame:CGRectMake(240,mynav.frame.origin.y,mynav.frame.size.width,mynav.frame.size.height)];
[mybutton setFrame:CGRectMake(240, mybutton.frame.origin.y, mybutton.frame.size.width, mybutton.frame.size.height)];
} completion:^(BOOL finished) {
sideview =true;
}];
That is really not the best way to configure frame.
Replace your code by this one:
[self.view addsubview:sideview];
[sidevieww setHidden:NO];
CGRect frameSideVieww = sidevieww.frame;
frameSideVieww.origin.x = frameSideVieww.origin.y = 0;
CGRect frameMyTable = mytable.frame;
frameMyTable.origin.x = 240;
CGRect frameMyNav = mynav.frame;
frameMyNav.origin.x = 240;
CGRect frameMyButton = mybutton.frame;
mybutton.origin.x = 240;
[UIView animateWithDuration:0.3 animations:^{
[sidevieww setFrame:frameSideVieww];
[mytable setFrame:frameMyTable];
[mynav setFrame:frameMyNav];
[mybutton setFrame:frameMyButton];
}completion:^(BOOL finished) {
sideview =true;
}];
Also, check if your class is subclass of UIViewController.

Display animating view within ViewController

EDITED:
I had created a slide in menu for my view and it works as i wanted, this was the original guide that I used.
http://www.youtube.com/watch?v=79ZQDzzOHLk
My goal was to get this programmed once in a class and get it to work on any view controller that i decided to call it in.
Thanks to #harsh.prasad and some additional research I have managed to get this to work to a point where it works as I want apart apart from linking buttons on to it.
So to update this question in the hope it may help someone else.
This is what I did:
I created a UIView class and called it MenuOne.
MenuOne.h
#import <UIKit/UIKit.h>
#interface TFMenuOne : UIView {
// Pop Up Menu
IBOutlet UIScrollView *scrollView;
IBOutlet UIButton *openMenu;
int draw1;
IBOutlet UIButton *backButton;
}
// Pop Up Menu
- (IBAction)openMenu_clicked:(id)sender;
// Reset draw1 to 0
- (void) resetView: (id) sender;
#property (retain, nonatomic) IBOutlet UIScrollView *scrollView;
#end
MenuOne.m
#import "TFMenuOne.h"
#implementation TFMenuOne
#synthesize scrollView;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
draw1 = 0;
scrollView = [[UIScrollView alloc] init];
[scrollView setBackgroundColor:[UIColor whiteColor]];
[scrollView setFrame:CGRectMake(0, 315, 568, 5)];
[scrollView setContentSize:CGSizeMake(568, 5)];
backButton = [[UIButton alloc] init];
[backButton setBackgroundColor:[UIColor greenColor]];
backButton.frame = CGRectMake(224, 350, 120, 30);
openMenu = [[UIButton alloc] init];
[openMenu setBackgroundImage:[UIImage imageNamed:#"menu-button-#2.png"]
forState:UIControlStateNormal];
openMenu.adjustsImageWhenHighlighted = NO;
[openMenu addTarget:self
action:#selector(openMenu_clicked:)
forControlEvents:UIControlEventTouchUpInside];
openMenu.frame = CGRectMake(256, 269, 64, 46);
[self addSubview:scrollView];
[self addSubview:backButton];
[self addSubview:openMenu];
}
return self;
}
// Allow for touch even through transparent View class
-(BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
for (UIView *view in self.subviews) {
if (!view.hidden && view.userInteractionEnabled && [view pointInside:[self convertPoint:point toView:view] withEvent:event])
return YES;
}
return NO;
}
- (void) resetView: (id) sender {
draw1 = 1;
[self openMenu_clicked:sender];
}
- (IBAction)openMenu_clicked:(id)sender {
if (draw1 == 0) {
draw1 = 1;
[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
scrollView.frame = CGRectMake(0, 260, 568, 60);
} completion:^(BOOL finished) {
}];
[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
openMenu.frame = CGRectMake(256, 214, 64, 46);
} completion:^(BOOL finished) {
}];
[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
backButton.frame = CGRectMake(224, 275, 120, 30);
} completion:^(BOOL finished) {
}];
} else {
draw1 = 0;
[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
scrollView.frame = CGRectMake(0, 315, 568, 5);
} completion:^(BOOL finished) {
}];
[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
openMenu.frame = CGRectMake(256, 269, 64, 46);
} completion:^(BOOL finished) {
}];
[UIView animateWithDuration:0.2 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
backButton.frame = CGRectMake(224, 350, 120, 30);
} completion:^(BOOL finished) {
}];
}
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
#end
After a lot of trial and error, in order to get this UIView class to appear on multiple ViewControllers I call the view like this in the m file of the view controller. The obstacles I ran in to was that the menu would open but when I left the view controller to go to another view controller the menu would be in the state it was in when i left, it wouldn't reset back to closed. The code below covered that thanks again to #harsh.prasad. I also managed to get the menu to animate in.
#interface TFMapViewController ()
{
TFMenuOne *menuView;
}
#end
#implementation TFMapViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
[menuView resetView:nil];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
menuView = [[TFMenuOne alloc] initWithFrame:CGRectMake(0, 51, 568, 320)];
[self.view addSubview:menuView];
}
- (void) viewDidAppear:(BOOL)animated
{
[UIView animateWithDuration:0.5 delay:0.5 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
menuView.frame = CGRectMake(0, 0, 568, 320);
} completion:^(BOOL finished) {
}];
}
- (void) viewDidDisappear:(BOOL)animated
{
[menuView resetView:nil];
[UIView animateWithDuration:0.0 delay:0.0 options:UIViewAnimationOptionBeginFromCurrentState animations:^{
menuView.frame = CGRectMake(0, 51, 568, 320);
} completion:^(BOOL finished) {
}];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
// Allows for Exit button to work
- (IBAction)returned:(UIStoryboardSegue *)segue {
}
#end
I you want you can use tabsController if that kind of feature you want, otherwise create a class of your slide in menu view and then you can use it in all of your views as you like. No same piece of code is to be rewritten.
EDIT:
Suppose you have created a class CustomMenuView which basically creates your menu view. So now you can use this in every view controller you want to use it in in the following way:
CustomMenuView *menuView = [CustomMenuView alloc] initWithFrame:CGRectMake(0, 200, 320, 100);
menuView.<properties you want to pass> = <set properties here>;
[self.view addSubView:menuView];
This will set the view with the custom menu and then you can handle the actions in this menu.
1)Here is an old tutorial for creating menu - http://www.raywenderlich.com/32054/how-to-create-a-slide-out-navigation-like-facebook-and-path/projectlayout
2)A better way is to create Drawer menu With container views. You can read more about container views from WWDC videos.
3)Or if you are lazy to d it yourself, try this library http://cocoacontrols.com/platforms/ios/controls/jtrevealsidebar
P.S. No , you do not havev to repeat the code.
You can try this,
First make a view on the origin point x = 0 y = 480 (for iphone4) and then run this code.
CGRect theFrame = self.viewMenuShare.frame;
theFrame.origin = CGPointMake(0, 480);
self.viewMenuShare.frame = theFrame;
theFrame.origin = CGPointMake(0,480 - 187);
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3f];
self.viewMenuShare.frame = theFrame;
[UIView commitAnimations];

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