I have been trying for a couple of days to find a way how to call action:selector on a custom button, derived from UIButton, which I want to associate with a pin annotation. The reason that I used a subclass is that I want to pass some data into this button object, in order to show another UIView displaying these data when the button is pressed.
The problem is that while executing, when I click on the pin annotation, it opens its button, and when I click on it, nothing happens. My showDetails: method is not called on receiving the touchupInside event as I set here:
[rightButton addTarget:self
action:#selector(showDetails:)
forControlEvents:UIControlEventTouchUpInside];
My question is how to inherit the methods of UIButton, like addTarget:action:forControlEvents:, buttonWithType:, etc., in order to use them in my subclass?
Here is the complete code concerning the problem:
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation
{
MKPinAnnotationView *annView=[[[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:#"MyPin"] autorelease];
annView.animatesDrop=FALSE;
annView.canShowCallout = YES;
[annView setSelected:YES];
if ([[annotation title] isEqualToString:#"Current Location"]) {
annView.pinColor = MKPinAnnotationColorRed;
}
else {
annView.pinColor = MKPinAnnotationColorPurple;
}
annView.calloutOffset = CGPointMake(-5, 5);
PlaceMark *pm=(PlaceMark *)annotation;
AddressItem *ai=[pm getData];
//Another problem is that i cant set buttonWithType:UIButtonTypeDetailDisclosure cause it generate error cause it is a method of UIbutton superclass
MyDetailButton* rightButton = [MyDetailButton buttonWithType:UIButtonTypeCustom];
[rightButton setData:ai];
[rightButton setTitle:annotation.title forState:UIControlStateNormal];
[rightButton addTarget:self action:#selector(showDetails:) forControlEvents:UIControlEventTouchUpInside];
annView.rightCalloutAccessoryView = rightButton;
return annView;
}
Thank you in advance. I hope that I have given a clear explanation of my problem.
I think you're on wrong way. To send action #selector your class need inherit from UIControl and not UIButton. Check out UIControl Class Reference I think the problem is here.
Do not hesitate to tell me if I did not understand your question.
Related
I have to display custom view on annotation click in ios, I have to display 7 images, name and detail disclosure button in custom view. On click of detail disclosure button , i have to call new view controller. How should i do it?
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
// Define your reuse identifier.
MKPinAnnotationView *annotationView=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"currentloc"];
annotationView.pinColor = MKPinAnnotationColorGreen;
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
// Adding Button on annotation callout which is your detail disclosure button//
UIButton *rightButton = [[UIButton alloc]initWithFrame:CGRectMake(0.0f,0.0f,28.0f,22.0f)];
[rightButton setImage:[UIImage imageNamed:#"rightArrow.png"] forState:UIControlStateNormal];
[rightButton addTarget:self
action:#selector(pressDetailBtn:)
forControlEvents:UIControlEventTouchUpInside];
annotationView.rightCalloutAccessoryView = rightButton;
annotationView.image=[UIImage imageNamed:#"orangePin.png"];
annotationView.opaque = NO;
return annotationView;
}
-(void)pressDetailBtn:(id)sender
{
YourVC code here
}
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.
I've recently come across this website and I've been trying to add to my call out view a button (from a image).
The code on the websites example works just fine, but when I tried to add in the same code to my project I'm not getting the same results.
There is obviously something I've missed but I cannot seem to work this one out!
Here is my code for annotating:
- (MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>) annotation{
MKPinAnnotationView *annView=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"currentloc"];
annView.pinColor = MKPinAnnotationColorGreen;
UIButton *advertButton = [UIButton buttonWithType:UIButtonTypeCustom];
advertButton.frame = CGRectMake(0, 0, 23, 23);
advertButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
advertButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
[advertButton setImage:[UIImage imageNamed:#"button_right.png"] forState:UIControlStateNormal];
[advertButton addTarget:self action:#selector(showLinks:) forControlEvents:UIControlEventTouchUpInside];
annView.rightCalloutAccessoryView = advertButton;
annView.animatesDrop=TRUE;
annView.canShowCallout = YES;
annView.calloutOffset = CGPointMake(-5, 5);
return annView;
}
Any help would be appreciated! :)
That guy is using a custom image to imitate the detail disclosure. You can actually get the standard detail disclosure quite easily:
[UIButton buttonWithType:UIButtonTypeDetailDisclosure];
Instead of setting the target like you did here:
[advertButton addTarget:self action:#selector(showLinks:) forControlEvents:UIControlEventTouchUpInside];
You can use the default delegate:
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
Sorry to answer my own question but this was solved by setting the delegate of the MKMapView to the ViewController. Phew, took me a while to figure that out and it's so simple!!
Is there either a way to implement UISwitch with custom graphics for the switch-states?
Or as an alternative the other way round, an UIButton with UISwitch functionality?
UIButton already supports a "switch" functionality.
Just set a different image in Interface Builder for the "Selected State Configuration", and use the selected property of UIButton to toggle its state.
set the image to show on selected state:
[button setImage:[UIImage imageNamed:#"btn_graphics"] forState:UIControlStateSelected];
and then on touch up inside selector, set:
button.selected = YES;
if you want this to cancel another button's selection, set:
otherButton.selected = NO;
To build on what PGB and nurne said above, after you set your states and attach a selector (event method) you would want to put this code in that selector.
- (IBAction)cost:(id)sender
{
//Toggle current state and save
self.buttonTest.selected = !self.buttonTest.selected;
/**
The rest of your method goes here.
*/
}
For programmatically inclined:
-(void) addToggleButton {
CGRect aframe = CGRectMake(0,0,100,100);
UIImage *selectedImage = [UIImage imageNamed:#"selected"];
UIImage *unselectedImage = [UIImage imageNamed:#"unselected"];
self.toggleUIButton = [[UIButton alloc] initWithFrame:aframe];
[self.toggleUIButton setImage:unselectedImage forState:UIControlStateNormal];
[self.toggleUIButton setImage:selectedImage forState:UIControlStateSelected];
[self.toggleUIButton addTarget:self
action:#selector(clickToggle:)
forControlEvents:UIControlEventTouchUpInside];
[self addSubview:self.toggleUIButton];
}
-(void) clickToggle:(id) sender {
BOOL isSelected = [(UIButton *)sender isSelected];
[(UIButton *) sender setSelected:!isSelected];
}
I want to change the image on UIButton, when User presses that button. So, I wrote
btnthumbnail2 setImage:[UIImage imageNamed:#"leaderboard_ov.png"] forState:UIControlStateNormal];
and after that I changed the view.
The image is changing but not display the changed image.I think the controll goes to next view tha's why it is happening. But I want to show the change, How can I do this?? Plz help me for this..
I am using Interface Builder, in which I added a UIButton to the view.
I defined the button selected by default and selected my image for the selected state (Use drop-down list in Inspector window to choose "Selected State Configuration" before selecting the image).
Create an IBAction in the controller and connect the button to that action.
Then see the code below:
-(IBAction) toggleUIButtonImage:(id)sender{
if ([sender isSelected]) {
[sender setImage:unselectedImage forState:UIControlStateNormal];
[sender setSelected:NO];
} else {
[sender setImage:selectedImage forState:UIControlStateSelected];
[sender setSelected:YES];
}
}
This is the simplest way that I am doing it and it works every time
-(void)buttonTouched:(id)sender
{
UIButton *btn = (UIButton *)sender;
if( [[btn imageForState:UIControlStateNormal] isEqual:[UIImage imageNamed:#"icon-Locked.png"]])
{
[btn setImage:[UIImage imageNamed:#"icon-Unlocked.png"] forState:UIControlStateNormal];
// other statements
}
else
{
[btn setImage:[UIImage imageNamed:#"icon-Locked.png"] forState:UIControlStateNormal];
// other statements
}
}
You can use other similar checks for other states such as SELECTED, ENABLED, HIGHLIGHTED.
The code you have there should work fine, but I'm guessing that the button image doesn't appear changed until the next run through the event loop, so you don't see it before the view gets switched out.
It's kind of a hack, but you could try delaying the view change just slightly so that the button will update.
So instead of this:
[btnthumbnail2 setImage:[UIImage imageNamed:#"leaderboard_ov.png"] forState:UIControlStateNormal];
[self showMyOtherView];
Try this:
[btnthumbnail2 setImage:[UIImage imageNamed:#"leaderboard_ov.png"] forState:UIControlStateNormal];
[self performSelector:#selector(showMyOtherView) withObject:self afterDelay:0.01];
To change the image for the selected state you have to call setImage for state UIControlStateSelected. You can set separate images for different states (Normal, Highlighted, Disabled, Selected, etc).
If you want to change the image when the button is clicked, this way, works perfectly:
-(IBAction)buttonClicked: (id)sender
{
UIButton *buttonObj = (UIButton*)sender;
[buttonObj setBackgroundImage:[UIImage imageNamed:#"myImage.png"]
forState:UIControlStateNormal];
}
The simplest way to accomplish this is to simply set the highlighted image in Interface Builder.
Building on Nicsoft's answer.
-(void)viewDidLoad {
[super viewDidLoad];
[self.button setImage:[UIImage imageNamed:#"unselectedImageName"] forState:UIControlStateNormal];
[self.button setImage:[UIImage imageNamed:#"selectedImageName"] forState:UIControlStateSelected];
}
-(IBAction)toggleButton:(UIButton *)sender {
sender.selected = !sender.selected;
// Add logic here
}
I wrote code that does exactly this last night, and I didn't have to resort to any strange delaying tactics. In this particular case, I'm doing it from inside a tableViewCell. This is more code than you asked for, but it shows the whole process I used. As you can see, I chose not to have any special image for the period of time DURING a button touch.
// Button set up, inside cellForRowAtIndexPath:
// imageFrame is just the rect that you want the button to occupy
[self setFavorite:[[UIButton alloc] initWithFrame:imageFrame]];
[[self favorite] addTarget:self action:#selector(toggleFavorite:)
forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:[self favorite]];
[self draw];
// definition of the callback specified above
- (void) toggleFavorite:(id) sender {
if (favoriteState == 0 ){
favoriteState = 1;
} else {
favoriteState = 0;
}
[self draw];
}
// the draw method, to set the images
// favOn and favOff are statically defined at the top of the class
- (void) draw {
if (favoriteState != 0) {
[[self favorite] setBackgroundImage:favOn forState:UIControlStateNormal];
[[self favorite] setBackgroundImage:favOn forState:UIControlStateHighlighted];
} else {
[[self favorite] setBackgroundImage:favOff forState:UIControlStateNormal];
[[self favorite] setBackgroundImage:favOff forState:UIControlStateHighlighted];
}
}
Hate to add to the plethora of answers, but:
Select images in IB for the button's default and selected states.
Connect an IBAction and keep it simple.
#IBAction func buttonTapped(sender: UIButton){sender.selected = !sender.selected}
Done.