I Have a UIButton and it has multiple actions associated with it
To play audio file
Toggle between play pause button
Display views
If i comment out the displayViewAction: it is working fine (i.e playing audio file and also toggling to pause button). But if I use the displayViewAction: method it is playing audio file displaying view but before displaying the view it should immediately toggle the state of the pause button, but it is not.
Code bellow for reference:
Code for UIButton:
UIButton *playpauseButton = [UIButton buttonWithType:UIButtonTypeCustom];
[playpauseButton addTarget:self action:#selector(playpauseAction:) forControlEvents:UIControlEventTouchUpInside];
[playpauseButton addTarget:self action:#selector(displayviewsAction:) forControlEvents:UIControlEventTouchUpInside];
playpauseButton.frame = CGRectMake(0, 0, 50, 50);
[playpauseButton setImage:[UIImage imageNamed:#"play.png"] forState:UIControlStateNormal];
[playpauseButton setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateSelected];
UIBarButtonItem *playpause = [[UIBarButtonItem alloc] initWithCustomView:playpauseButton];
Code for Playpause button:
-(void)playpauseAction:(id)sender
{
if ([audioPlayer isPlaying]){
[sender setImage:[UIImage imageNamed:#"play.png"] forState:UIControlStateNormal];
[audioPlayer pause];
}
else {
[sender setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal];
[audioPlayer play];
}
}
Code for display view action:
- (void)displayviewsAction:(id)sender
{
self.view = [[[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]]autorelease];
[self.view setFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
PageOneViewController *viewController = [[[PageOneViewController alloc] init]autorelease];
[self.view addSubview:viewController.view];
}
Can anyone please advise how I can make it work this way?
Attach only one action to your UIButton. When this action is called, perform various tasks depending upon the state of the application.
You can't attach many actions to your UIButton.
Why don't you attach a function which toggle play/pause, then displays the views?
[playpauseButton addTarget:self action:#selector(playpauseActionAndDisplayView:) forControlEvents:UIControlEventTouchUpInside];
then
-(void)playpauseActionAndDisplayView:(id)sender
{
[self playpauseAction:sender];
[self displayviewsAction:sender];
}
Changed the UIControlState in the playpauseAction method like this
-(void)playpauseAction:(id)sender
{
if
([audioPlayer isPlaying]){
[sender setImage:[UIImage imageNamed:#"play.png"] forState:UIControlStateSelected];
[audioPlayer pause];
} else {
[sender setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal];
[audioPlayer play];
[self displayviewsAction:sender];
}
}
and it worked.
Related
I'm trying to implement an analog of segmented control with two buttons. In default state they have no images, only labels, in selected one they have background image. I want to activate control with TouchDown event.
here is the code (I removed all unnecessary things):
-(IBAction) onButton1
{
button1.selected = YES;
button2.selected = NO;
}
-(IBAction) onButton2
{
button1.selected = NO;
button2.selected = YES;
}
the problem is: assume button1 is selected. When I touch button2 it does not change its image to "selected" image (there is no default image, as I've said), but when I release finger it changes. Also, if I touch already selected button it removes "selected" image and return it when I release it.
I've set highlighted state of buttons, so they have "selected" image in that state, but it did not help (not only in IB, but also with [button setBackgroundImage:[UIImage imageNamed:#"selected.png"] forState:UIControlStateHighlighted];). I've set adjustsImageWhenHighlighted = NO, that did not help too, again, in both program way and IB.
I've seen a lot of similar (but not identical) questions here, but they did not work for me.
Thanks in advance
Since, you wanted to activate the action at touch down event, I assume that you dont need highlighting. Try the following code
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
button1 = [UIButton buttonWithType:UIButtonTypeCustom];
button1.frame = CGRectMake(10.0f, 10.0f, 50.0f, 50.0f);
[button1 setBackgroundImage:[UIImage imageNamed:#"btn.jpeg"] forState:UIControlStateNormal];
[button1 setBackgroundImage:[UIImage imageNamed:#"btnsel.jpeg"] forState:UIControlStateSelected];
[button1 addTarget:self action:#selector(button1Action:) forControlEvents:UIControlEventTouchDown];
[button1 addTarget:self action:#selector(button1TouchUp:) forControlEvents:UIControlEventTouchUpInside|UIControlEventTouchUpOutside];
[self.view addSubview:button1];
button1.selected = YES;
button2 = [UIButton buttonWithType:UIButtonTypeCustom];
button2.frame = CGRectMake(80.0f, 10.0f, 50.0f, 50.0f);
[button2 setBackgroundImage:[UIImage imageNamed:#"btn.jpeg"] forState:UIControlStateNormal];
[button2 setBackgroundImage:[UIImage imageNamed:#"btnsel.jpeg"] forState:UIControlStateSelected];
[button2 addTarget:self action:#selector(button2Action:) forControlEvents:UIControlEventTouchDown];
[button2 addTarget:self action:#selector(button2TouchUp:) forControlEvents:UIControlEventTouchUpInside|UIControlEventTouchUpOutside];
[self.view addSubview:button2];
}
- (void)button1Action:(UIButton*)sender
{
button1.highlighted = NO;
button1.selected = YES;
button2.selected = NO;
}
- (void)button2Action:(UIButton*)sender
{
button2.highlighted = NO;
button2.selected = YES;
button1.selected = NO;
}
- (void)button1TouchUp:(id)sender
{
button1.highlighted = NO;
}
- (void)button2TouchUp:(id)sender
{
button2.highlighted = NO;
}
I have dynamically created some list of RadioButtons with some values. pro grammatically I changed the button state and changed the image for selected and unselected. but the problem is i can select the all radioButtons at same time. actually I need to select one at a time.
when I clicked the next RadioButton, previously selected button state should be changed to non-selected.
Here is my code, I tried with changing image, but ...some problem with my code.
RadioButton = [UIButton buttonWithType:UIButtonTypeCustom];
[RadioButton setFrame:CGRectMake(0.0f, 0.0f, 20, 20)];
[RadioButton setCenter:CGPointMake(116.0,p1)];
[RadioButton setSelected:NO];
[RadioButton setImage:[UIImage imageNamed:#"uncheck.png"] forState:UIControlStateNormal];
[RadioButton addTarget:self action:#selector(RadioButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
[self.scrollView addSubview:RadioButton];
-(void)RadioButtonTapped:(id)sender
{
UIButton *RadioButton1 = (UIButton*)sender ;
[self radiobuttonAction:RadioButton1];
}
-(void)radiobuttonAction:(UIButton *)Button
{
if(![Button isSelected])
{
[Button setSelected:YES];
[Button setImage:[UIImage imageNamed:#"radio_active.png"] forState:UIControlStateSelected]; //not working, button image is not changing
}
else
{
[Button setSelected:NO];
[Button setImage:[UIImage imageNamed:#"radio_inactive.png"] forState:UIControlStateNormal];
}
}
where can I change the image of previously selected button.
thanks in advance
Deselect all the buttons when you select one. If you have buttons in your scroll view you can user this code:
//Your Method
-(void)RadioButtonTapped:(id)sender
{
UIButton *RadioButton1 = (UIButton*)sender;
[self deselectAll];
[self radiobuttonAction:RadioButton1];
}
- (void) deselectAll : (UIScrollView *) scrollView{
NSArray *viewArray = [scrollView subviews];
for (UIView *v in viewArray){
if([v isKindOfClass:[UIButton class]]){
[((UIButton *)v) setSelected:NO];
}
}
}
EDIT: But if you want to give it real radio button effect (in which one is always selected, and only one is selected) it will be more easy to you. Use following code:
//A globle refButton
UIButton *refButton = nil;
//Set image for both state:
[RadioButton setImage:[UIImage imageNamed:#"uncheck.png"] forState:UIControlStateNormal];
[RadioButton setImage:[UIImage imageNamed:#"check.png"] forState:UIControlStateSelected];
//make any of above default select: may be the last one and pass that to `refButton`
refButton = RadioButton;
//Your Method
-(void)RadioButtonTapped:(id)sender
{
[refButton setSelected:NO];
refButton = (UIButton*)sender;
[refButton setSelected:YES];
}
Tag the button at the time of creation.
When button tapped, get the buttons through tag. Deselect all buttons. Update current button which you have received as a n argument.
assuming you want to add 5 radio buttons.
- (void)viewDidLoad
{
for (int i = 0; i < 5; i++) {
UIButton* RadioButton = [UIButton buttonWithType:UIButtonTypeCustom];
[RadioButton setFrame:CGRectMake(0.0f, 0.0f, 20, 20)];
[RadioButton setCenter:CGPointMake(116.0, i * 40)];
// [RadioButton setTag:i * 10];
[RadioButton setSelected:NO];
[RadioButton setImage:[UIImage imageNamed:#"unCheck.png"] forState:UIControlStateNormal];
[RadioButton addTarget:self action:#selector(RadioButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
[self.scrollView addSubview:RadioButton];
}
}
//do not forget to declared this in your header file
-(void)RadioButtonTapped:(UIButton*)button;
{
for (UIButton *btn in self.scrollView.subviews) {
[btn setImage:[UIImage imageNamed:#"unCheck.png"] forState:UIControlStateNormal];
}
[button setImage:[UIImage imageNamed:#"check.png"] forState:UIControlStateNormal];
}
the code above updates the UI, sets the image of all buttons to "uncheck" then changes the image of the last pressed button to "check".
create buttons like this,
for(int i=0;i<4;i++)
{
RadioButton = [UIButton buttonWithType:UIButtonTypeCustom];
RadioButton.tag = i*100;
[RadioButton setFrame:CGRectMake(0.0f, 0.0f, 20, 20)];
[RadioButton setCenter:CGPointMake(116.0,p1)];
[RadioButton setSelected:NO];
[RadioButton setImage:[UIImage imageNamed:#"uncheck.png"] forState:UIControlStateNormal];
[RadioButton addTarget:self action:#selector(RadioButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
[self.scrollView addSubview:RadioButton];
}
add action like this,
-(void)radiobuttonAction:(UIButton *)Button
{
UIButton *Button = (UIButton*)sender;
for(UIButton * btn in self.scrollview.subViews)
{
if(btn.tag == Button.tag)
{
if(![Button isSelected])
{
[Button setSelected:YES];
[Button setImage:[UIImage imageNamed:#"radio_active.png"] forState:UIControlStateSelected]; //not working, button image is not changing
}
else
{
[Button setSelected:NO];
[Button setImage:[UIImage imageNamed:#"radio_inactive.png"] forState:UIControlStateNormal];
}
}
else
{
//do selected or de-selected code for other buttons
}
}
This rewind method is for rewind button as well as for play button.
-(void)rewind:(id)sender
{
[timer invalidate];
audioPlayer.currentTime = 0;
MainViewController *viewController = [[MainViewController alloc] init];
viewController.view.frame = CGRectMake(0, 0, 320, 480);
[self.view addSubview:viewController.view];
[self.view addSubview:toolbar];
[viewController release];
if([audioPlayer isPlaying])
{
[sender setImage:[UIImage imageNamed:#"Play Icon.png"] forState:UIControlStateSelected];
[audioPlayer pause];
[self pauseTimer];
[self pauseLayer:self.view.layer];
}else{
[sender setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal];
[audioPlayer play];
[self resumeTimer];
[self resumeLayer:self.view.layer];
if(isFirstTime == YES)
{
self.timer = [NSTimer scheduledTimerWithTimeInterval:11.0
target:self
selector:#selector(displayviewsAction:)
userInfo:nil
repeats:NO];
isFirstTime = NO;
}
}
}
Now in this method sender is rewind button and toggling of play/pause is happening on rewind button whereas i want this toggling on play button rather then sender which is rewind button. So i tried giving the name of the actual button on which i want toggling to happen and i defined that button as play button in my code and whose action method i have added in this rewind method.
That's how defined the play button
//Add Play Button
UIButton *playButton = [UIButton buttonWithType:UIButtonTypeCustom];
[playButton addTarget:self action:#selector(playpauseAction:) forControlEvents:UIControlEventTouchUpInside];
playButton.frame = CGRectMake(0, 0, 30, 30);
[playButton setImage:[UIImage imageNamed:#"Play Icon.png"] forState:UIControlStateNormal];
[playButton setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateSelected];
UIBarButtonItem *play = [[UIBarButtonItem alloc] initWithCustomView:playButton];
and this is the method of play button which i added in the rewind button
-(void)playpauseAction:(id)sender
{
if([audioPlayer isPlaying])
{
[sender setImage:[UIImage imageNamed:#"Play Icon.png"] forState:UIControlStateSelected];
[audioPlayer pause];
[self pauseTimer];
[self pauseLayer:self.view.layer];
}
else
{
[sender setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal];
[audioPlayer play];
[self resumeTimer];
[self resumeLayer:self.view.layer];
if(isFirstTime == YES)
{
self.timer = [NSTimer scheduledTimerWithTimeInterval:11.0
target:self
selector:#selector(displayviewsAction:)
userInfo:nil
repeats:NO];
isFirstTime = NO;
}
}
}
now problem i m facing at this time is that when i m clicking the rewind button toggling should happen on play button than rewind button.
But to fix this problem i simply replaced sender with playButton in the rewind method like this
[playButton setImage:[UIImage imageNamed:#"Play Icon.png"] forState:UIControlStateSelected];
but then i get warning message in red that use of undeclared identifier playButton.
How can i tell rewind method to do toggling on playButton rather then on rewind button.
Please help.
Thanks.
Your "undeclared identifier playButton" is telling you that you don't have an instance variable playButton.
It is probably only visible in the method where you created it, but you need to save it into an iVar to be able to access it from the other method.
I can't get this code to work.
Declared playpauseButton just above the given below statements
UIButton *playpauseButton = [UIButton buttonWithType:UIButtonTypeCustom];
Getting local declaration of playpauseButton hides instance variable warning message for following statements
playpauseButton addTarget:self action:#selector(playpauseAction:) forControlEvents:UIControlEventTouchUpInside];
playpauseButton.frame = CGRectMake(0, 0, 30, 30);
[playpauseButton setImage:[UIImage imageNamed:#"Play Icon.png"] forState:UIControlStateNormal];
[playpauseButton setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateSelected];
UIBarButtonItem *play = [[UIBarButtonItem alloc] initWithCustomView:playpauseButton];
After i defined playpauseAction method
-(void)playpauseAction:(id)sender {
if( playpauseButton.state == UIControlStateNormal ){
[sender setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateSelected];
[audioPlayer play];
self.timer = [NSTimer scheduledTimerWithTimeInterval:11.0
target:self
selector:#selector(displayviewsAction:)
userInfo:nil
repeats:NO];
} else if (playpauseButton.state == UIControlStateSelected)
{
[sender setImage:[UIImage imageNamed:#"Play Icon.png"] forState:UIControlStateNormal];
[audioPlayer pause];
[self pauseTimer];
} else if (playpauseButton.state == UIControlStateNormal)
{
[sender setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateSelected];
[audioPlayer play];
[self resumeTimer];}}
Some help please.
Thanks.
It's telling you that you have two declarations of playpauseButton. One is in the interface section of your class (the instance variable) and the other is a local variable.
It's not an actual error but the warning tells you that you may get results different from what you want.
I have added multiple actions to one button
Play audiofile
Display array of views
Button is playing audiofile but not displaying views.
UIButton *playpauseButton = [UIButton buttonWithType:UIButtonTypeCustom];
[playpauseButton addTarget:self action:#selector(playpauseAction:) forControlEvents:UIControlEventTouchUpInside];
[playpauseButton addTarget:self action:#selector(displayviewsAction:) forControlEvents:UIControlEventTouchUpInside];
playpauseButton.frame = CGRectMake(0, 0, 50, 50);
[playpauseButton setImage:[UIImage imageNamed:#"play.png"] forState:UIControlStateNormal];
[playpauseButton setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateSelected];
UIBarButtonItem *playpause = [[UIBarButtonItem alloc] initWithCustomView:playpauseButton];
Play Pause Action coding
-(void)playpauseAction:(id)sender
{
if
([audioPlayer isPlaying]){
[sender setImage:[UIImage imageNamed:#"play.png"] forState:UIControlStateNormal];
[audioPlayer pause];
} else {
[sender setImage:[UIImage imageNamed:#"pause.png"] forState:UIControlStateNormal];
[audioPlayer play];
}
}
DisplayviewsAction coding
- (void)displayviewsAction:(id)sender
{
CGRect pageViewRect = self.view.bounds;
pageViewRect = CGRectInset(pageViewRect, 30.0, 30.0);
self.pageViewController.view.frame = pageViewRect;
// Configure the page view controller
UIPageViewController *pageViewController = [[[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil]autorelease];
NSArray *viewControllers = [NSArray arrayWithObject:pageViewController];
[self.pageViewController setViewControllers:viewControllers
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:nil];
[self.view addSubview:self.pageViewController.view];
}
Any advice what i m missing in the code or doing wrong.
Thanks for help.
Here are some minor corrections you should make - they may not all help with the problem, but you never know.
Add a completion block here:
[self.pageViewController setViewControllers:viewControllers
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:nil];
I don't remember for sure, but I think setViewControllers is done asynchronously - nothing cannot be added until after the completion handler is done. To add the block, you simply put a ^ and a block of code in (like a normal method):
[self.pageViewController setViewControllers:viewControllers
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:^{
// your code here.
}];
This may fix the problem, but I cannot be sure until I can get back to my computer.
You should also put an NSLog at the beginning of every method, at least until you are done debugging. That way, you always know what is being called and what isn't. If it is not called, try removing the autorelease from the pageViewController - it may be released because it isn't being used.
I think the issue is in displayviewsAction, try something more simple like:
- (void) displayviewsAction:(id)sender
{
UIView* testView = [[UIView alloc] initWithFrame:CGRectInset(self.view.bounds, 30.0, 30.0)];
testView.backgroundColor = [UIColor greenColor];
[self.view addSubview:testView];
[testView release];
}
That should help you narrow down the problem. Depending on what your final aim is you might not need all those view controllers; instead consider UIView's transitionFromView... for the animation effects.