MKAnnotationView's callout not refreshing properly - iphone

I've got a problem with the accessory views in the MKAnnotationViews, but it only occurs when using the iOS 3 SDK. The 3.1.3 version specifically.
I have a subclass of MKAnnotationView and I create instances of it the usual way:
SourceAnnotationView *annotationView = (SourceAnnotationView *)[self.mapView dequeueReusableAnnotationViewWithIdentifier:kDefaultSourceAnnotationID];
if (annotationView == nil) {
#if DEBUG
NSLog(#"RecordViewController viewForAnnotation source %d",[sourceAnnotation.ioiIdent intValue]);
#endif
annotationView = [[[SourceAnnotationView alloc] initWithAnnotation:sourceAnnotation reuseIdentifier:kDefaultSourceAnnotationID] autorelease];
annotationView.delegate = self;
}
Later on in the code, I change the content of the callout bubble by doing:
UIButton *deleteButton = [UIButton buttonWithType:UIButtonTypeCustom];
[deleteButton setImage:[UIImage imageNamed:kDeleteAudioButtonImageName] forState:UIControlStateNormal];
deleteButton.frame = CGRectMake(0, 0, kAnnotationViewLeftAccessoryWidth, kAnnotationViewLeftAccessoryHeight);
deleteButton.tag = kDeleteAudioButtonTag;
deleteButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
deleteButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
[deleteButton addTarget:self action:#selector(calloutButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
selectedAnnotationView.leftCalloutAccessoryView = deleteButton;
UIButton *editAudioInfoButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
editAudioInfoButton.frame = CGRectMake(0, 0, kAnnotationViewRightAccessoryWidth, kAnnotationViewRightAccessoryHeight);
editAudioInfoButton.tag = kEditInfoButtonTag;
editAudioInfoButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
editAudioInfoButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
[editAudioInfoButton addTarget:self action:#selector(calloutButtonPressed:) forControlEvents:UIControlEventTouchUpInside];
selectedAnnotationView.rightCalloutAccessoryView = editAudioInfoButton;
with kAnnotationViewRightAccessoryWidth and kAnnotationViewRightAccessoryHeight being both equal to 32.
When I no longer need these buttons, I try (and in most cases manage) to get rid of them like this:
selectedAnnotationView.rightCalloutAccessoryView = nil;
selectedAnnotationView.leftCalloutAccessoryView = nil;
In iOS 4, this results in the accessory views dissapearing and everything working beautifully. However, in iOS 3 the two buttons stay, even though they're not clickable, as if they were not completely removed from the callout's view.
Also, if I click any other annotation view the two buttons appear.
Does anyone know how to solve this?
Thanks!
EDIT:
Here is a picture of what happens:

make call after
selectedAnnotationView.rightCalloutAccessoryView = nil;
selectedAnnotationView.leftCalloutAccessoryView = nil;
[selectedAnnotationView setNeedsDisplay];

Related

How to show custom callout with two button in mkmapview in iPhone?

I want to show a custom callout with two button , and I also want action on both buttons ,
I try that but not do this type of callout on map, this isn't really exactly what I wanted. As I am making an iPhone application, Since I am new to MKMapview its getting difficult for me to do the same. How to show custom callout with two button?
You can go for Left and right calloutaccessoryview Look at HERE
//ANNOTATION VIEW SETTING DELEGATE
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
MKPinAnnotationView *myPin = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:#"reuseString"];
myPin.draggable = NO;
myPin.canShowCallout = YES;
myPin.pinColor = MKPinAnnotationColorRed;
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeCustom];
rightButton.frame = CGRectMake(0, 0, 50, 30);
[rightButton setTitle:#"Info!" forState:UIControlStateNormal];
[rightButton setBackgroundImage:[UIImage imageNamed:#"image.png"] forState:UIControlStateNormal];
rightButton.showsTouchWhenHighlighted = YES;
[rightButton addTarget:self action:#selector(rightAcccoryViewButtonCLicked) forControlEvents:UIControlEventTouchUpInside]; //rightAcccoryViewButtonCLicked is a function
myPin.rightCalloutAccessoryView = rightButton;
return myPin;
}
Similarly you can use the leftCalloutAccessoryView and add another button.

ExclusiveTouch per UIView

I have a two UIViews filled with UIButtons. I want to only allow one button to accept touches at a time PER UIView. That is to say I want multitouch working if you have one finger in each group of buttons but not if you have both fingers in the same group.
Of course exclusiveTouch set on the buttons makes sure only one button at a time is touched but it does it for the entire window. Is there a way to only allow one touch per UIView instead of the entire window?
Update: So to give a better understand of the desired function. I want a user to be able to select a red and blue card using multitouch. Easy. BUT I don't want them to be able to select two red cards or anything like that. Problem is if I turn on exclusiveTouch on the cards only one card in the WHOLE WINDOW can be selected at a time. The desired functionality is to have exclusiveTouch only operate PER UIVIEW which each set of cards is wrapped in its own UIView already.
Update 2: Just wanted to throw in that I am trying to find a solution that DOESN'T involve subclassing or otherwise overriding UIView's touch controllers. That is a last resort.
When touching down one of your buttons, you may set userInteractionEnabled property of another button to NO and set it back to YES while touching up.
UPDATE 1
Sorry, I was an idiot.
UPDATE 2
...
UPDATE 3
Finally I got back to XCode. This code works (if I understood your aim correctly):
#interface ViewController : UIViewController {
NSMutableArray *leftButtonsArray;
NSMutableArray *rightButtonsArray;
}
#end
//
#implementation ViewController
#pragma mark - Objects Processing
- (void)buttonDownAct:(UIButton *)sender {
sender.backgroundColor = [UIColor greenColor];
NSArray *targetArray = nil;
if ([leftButtonsArray indexOfObject:sender] == NSNotFound)
targetArray = rightButtonsArray;
else
targetArray = leftButtonsArray;
for (UIButton *button in targetArray)
if (button != sender)
button.userInteractionEnabled = NO;
}
- (void)buttonUpAct:(UIButton *)sender {
NSArray *targetArray = nil;
if ([leftButtonsArray indexOfObject:sender] == NSNotFound) {
targetArray = rightButtonsArray;
sender.backgroundColor = [UIColor blueColor];
}
else {
targetArray = leftButtonsArray;
sender.backgroundColor = [UIColor redColor];
}
for (UIButton *button in targetArray)
button.userInteractionEnabled = YES;
}
#pragma mark - View lifecycle
- (void)loadView {
leftButtonsArray = [[NSMutableArray alloc] init];
rightButtonsArray = [[NSMutableArray alloc] init];
self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] applicationFrame]];
self.view.backgroundColor = [UIColor whiteColor];
float desiredWidth = self.view.frame.size.width / 4, desiredHeight = self.view.frame.size.height / 2;
for (int i = 0; i < 4; i++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectInset(CGRectMake(desiredWidth * (i % 2), desiredHeight * (i / 2), desiredWidth, desiredHeight), 10, 10);
[button setBackgroundColor:[UIColor redColor]];
[button addTarget:self action:#selector(buttonDownAct:) forControlEvents:UIControlEventTouchDown];
[button addTarget:self action:#selector(buttonUpAct:) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
[self.view addSubview:button];
[leftButtonsArray addObject:button];
}
for (int i = 0; i < 4; i++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectInset(CGRectOffset(CGRectMake(desiredWidth * (i % 2), desiredHeight * (i / 2), desiredWidth, desiredHeight), self.view.frame.size.width / 2, 0), 10, 10);
[button setBackgroundColor:[UIColor blueColor]];
[button addTarget:self action:#selector(buttonDownAct:) forControlEvents:UIControlEventTouchDown];
[button addTarget:self action:#selector(buttonUpAct:) forControlEvents:UIControlEventTouchUpInside | UIControlEventTouchUpOutside];
[self.view addSubview:button];
[rightButtonsArray addObject:button];
}
}
#end
Didnt try this, but anyway.
Can you make two UIView on the main view, one for red buttons and one for blue ones. And set exclusive touch for your buttons?

Method to create UIButtons

this is my first post, any help would be greatly appreciated.
I have to create a number of UIButtons programmatically, which I have done, but the code gets quite messy when there are alot of buttons so I have written a method that will take a UIbutton, string and UIcolor as input and set the rest of the UIButton attributes for me. The problem is the buttons don't seem to be created. Is what I'm trying possible or am I going about it the wrong way.
The method
-(void)makeButton:(UIButton *)name titleOfButton:(NSString *)title buttonColor:(UIColor *)color {
name =[[UIButton alloc] initWithFrame:(CGRectMake(400,400,150,100))];
[name setAlpha:(0.5)];
[name setBackgroundColor: color];
[name setTitle:title forState:UIControlStateNormal];
name.titleLabel.font = [UIFont systemFontOfSize:16];
name.titleLabel. numberOfLines = 0; // Dynamic number of lines
name.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
name.titleLabel.textColor = [UIColor blackColor];
[myView addSubview:name];
}
and to call the method
[self makeButton:JDLabel
titleOfButton:#"JD"
buttonColor:[UIColor redColor]];
The method has been declared in the header file and the buttons at the top of the class.
This is some code to get you started. This will work if you paste it to your view controller, generally put it in the view you want but change "self.view" to "self" or any view you want as long as you have the reference to it. Just call "addSomeButtons" on "viewDidLoad" or as some target..
- (void)buttonPressed:(UIButton *)sender {
NSLog(#"button %d pressed", sender.tag+1);
}
- (void)makeButtonWithtitle:(NSString *)title andColor:(UIColor *)color atPositionIndex:(NSInteger)index {
const CGFloat buttonHeight = 60.0f;
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(.0f, buttonHeight*index, 300.0f, buttonHeight)];
button.tag = index;
[button setAlpha:(0.5)];
[button setBackgroundColor: color];
[button setTitle:title forState:UIControlStateNormal];
button.titleLabel.font = [UIFont systemFontOfSize:16];
button.titleLabel. numberOfLines = 0; // Dynamic number of lines
button.titleLabel.lineBreakMode = UILineBreakModeWordWrap;
button.titleLabel.textColor = [UIColor blackColor];
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:button];
[button release];
}
- (void)addSomeButtons {
for(int i=0; i<10; i++) {
[self makeButtonWithtitle:[NSString stringWithFormat:#"button %d", i+1] andColor:[UIColor greenColor] atPositionIndex:i];
}
}
Anyway what you are trying to do is very common and very possible. For instance I never ever ever use the interface builder.
set the different tag value of to separate the button from another button like:
button.tag = 1;
here you should use variable like
in .h
int i ;
in .m
button.tag = i;
and set the frame size of one button to another button
UIButton *name = [UIButton buttonWithType:UIButtonTypeRoundRectangle];
name.frame = CGRectMake(10*i,10*i,150,100);
i++;
UIButtons are getting created but getting overlapped over each other.. u just need to change the frame with every method call too.. 400,400 will create the button off screen .. i don't think thats what u want .. try something like 160,240
You might want to consider creating the Buttons in Interface Builder, which I find much more convenient for setting the size, colors etc.
You can then reference the buttons in the code via either with an IBOutlet per Button or with an IBOutletCollection, which let's you "group" a number of UIViews in one Outlet:
Simply create your UIButtons in Interfacebuilder and place them next to your main view, so that they won't be displayed initially.
CMD + Click all buttons and CTRL + Drag to your .h file and create an IBOutletCollection which will eventually look like this in your code:
#property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *allMyButtonsFromIB;
Now you can access the buttons in the implementation via self.allMyButtons, which is an NSArray
-(void)createButtonWithTitle:(NSString*)title andColor:(UIColor*)color andFrame:(CGRect)frame{
UIButton *lButton = [UIButton buttonWithType:UIButtonTypeCustom];
[lButton setFrame:frame];
[lButton setTitle:title forState:UIControlStateNormal];
lButton.titleLabel.font = [UIFont systemFontOfSize:16];
[lButton setBackgroundColor:color];
[self.view addSubview:lButton];
lButton = nil;
}
You can change the frame values to put the buttons at appropriate positions on the view.

UIButton not being clicked in iPhone programming

I've created a UIButton on a view and on action of the UIButton[UIButton* button1_obj] one more button[UIButton* button2_obj] is created on same view.
i'm facing these 2 issues...please guide me how to proceed.
button1_obj is appearing when i run my project, but its not being clicked or highlighted, nor any exception is thrown.
On action of button1_obj , button2-obj has to appear on the same view, how to clear the view before placing button2_obj on it.
Code for question (1):
-(void)start
{
NSLog(#"--------------------------------------------------------------------");
NSLog(#"Entered CView start");
//define size and position of view
subMainView_G_obj = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 480, 320)]; //initilize the view
//subMainView_G_obj.autoresizesSubviews = YES; //allow it to tweak size of elements in view
UIButton_G_obj = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
UIButton_G_obj.frame = CGRectMake(100,70, 150, 50);
UIButton_G_obj.backgroundColor = [UIColor clearColor];
//UIButton_G_obj.adjustsImageWhenHighlighted = YES;
[UIButton_G_obj setTitle:#"UI" forState:UIControlStateNormal];
[UIButton_G_obj addTarget:self action:#selector(action:) forControlEvents:UIControlEventTouchUpInside];
[subMainView_G_obj addSubview:UIButton_G_obj];
UIButton_G_obj = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
UIButton_G_obj.frame = CGRectMake(100,150, 150, 50);
UIButton_G_obj.backgroundColor = [UIColor clearColor];
UIButton_G_obj.adjustsImageWhenHighlighted = YES;
[UIButton_G_obj setTitle:#"Configuration" forState:UIControlStateNormal];
[UIButton_G_obj addTarget:self action:#selector(action:) forControlEvents:UIControlEventTouchUpInside];
[subMainView_G_obj addSubview:UIButton_G_obj];
NSLog(#"Leaving CView start");
NSLog(#"--------------------------------------------------------------------");
}
- (void)action:(id) sender
{
NSLog(#"Inside action method.. On click of First View");
buttonUIObj = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
buttonUIObj.frame = CGRectMake(100,160,100,50);
[buttonUIObj setTitle:#"Next View" forState:UIControlStateNormal];
buttonUIObj.backgroundColor = [UIColor clearColor];
[subMainView_G_obj addSubview:buttonUIObj];
}
i've declare UIButton_G_obj,buttonUIObj,subMainView_G_obj GLOBALLY.
Hard to know what the problem with button1_obj is, without seeing code. However, for (2), you will probably want to remove button1_obj by calling [button1_obj removeFromSuperview].
About problem 1:
First of all both your buttons are named the same. Therefore you have a memory leak because your are allocating space for your button twice. Use different names for your buttons.
About problem 2:
You could hide button 2 until button 1 is pressed: In -(void)start
UIButton_G_obj_1.tag = 1;
...
UIButton_G_obj_2.hidden = YES;
UIButton_G_obj_2.tag = 2;
And in the action method you can unhide the button:
if (sender.tag == 1) {
UIButton_G_obj_2.hidden = NO;
}

How to add a UIButton at runtime

I am trying to add a UIButton at runtime however it is not visible. What am I doing wrong?
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
UIButton *btn = [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
btn.frame = CGRectMake(0, 0, 100, 25);
btn.backgroundColor = [UIColor clearColor];
[btn setTitle:#"Play" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(buttonClick:)
forControlEvents:UIControlEventTouchUpInside];
btn.center = self.center;
[self addSubview:btn];
}
return self;
}
First, make sure the initWithFrame: method is being called. If your view is in a Nib, initWithCoder: is being called instead.
Second, is the button the only subview (from your code it looks like it is, but you never know). The button could be hidden behind another subview. Call bringSubviewToFront: if you need to.
Finally, is the view itself visible? Is it big enough to show the button? Given your example, if the view is less than 100 pixels wide, the button won't show because it will get clipped by the view's bounds.
You must release btn and remove ":" in buttonClick:
UIButton *btn= [[UIButton buttonWithType:UIButtonTypeRoundedRect] retain];
btn.frame = CGRectMake(0, 0, 100, 25);
btn.backgroundColor = [UIColor clearColor];
[btn setTitle:#"Play" forState:UIControlStateNormal];
[btn addTarget:self action:#selector(buttonClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
[btn release];
if it still doesn't work, try removing the : at the end of the selector name: #selector(buttonClick)
You don't need to retain the UIButton because it is retained by [self.view addSubview:btn];
First check whether your code is executing the initwithFrame method.
Because if you are loading the view from nib i.e using
NSArray *xibviews = [[NSBundle mainBundle] loadNibNamed: #"MySubview" owner: mySubview options: NULL];
MySubview *msView = [xibviews objectAtIndex: 0];
[self.view addSubview:msView];
Then the initWithFrame part will not be executing.So please check once.