Fading a UIView with a subviewed button - xcode

I'm trying to create a button that fades out and then in when I open the page.
Here is the current code that i'm using, it doesn't work to fade the buttons in/ out:
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view
{
if (index == 0) {
view = [[[NSBundle mainBundle] loadNibNamed:#"nib1" owner:self options:nil] lastObject];
}else {
view = [[[NSBundle mainBundle] loadNibNamed:#"nib2" owner:self options:nil] lastObject];
UIView *containView = [[UIView alloc] initWithFrame:CGRectMake(50, 50, 60, 100)];
_btn = [UIButton buttonWithType:UIButtonTypeCustom];
_btn.frame = CGRectMake(30, 90, 40, 30 );
[_btn setBackgroundImage:[UIImage imageNamed:#"playButton.png"] forState:UIControlStateNormal];
[_btn addTarget:self action:#selector(fadeButton:) forControlEvents:UIControlEventTouchUpInside];
//[self fadeOut:_btn withDuration:1.0 andWait:1.0];
[containView addSubview:_btn];
[containView setAlpha:0.0];
[view addSubview:containView];
[UIView beginAnimations:nil context:nil];
[containView setAlpha:1.0];
[UIView commitAnimations];
}
return view;
}
I've also tried using:
[UIView animateWithDuration:0.5 animations:^{_btn.alpha = 1.0;}];
None of those work. Does anyone have any tips on how to fade a subview out? Thanks

When you call [UIView commitAnimations], the animations are animating at the same time.
When you want to animate something after an other animation try to nest animation blocks with completion:
[UIView animateWithDuration:0.5 animations:^
{
//animate out
}
completion:^ (BOOL finished)
{
[UIView animateWithDuration:0.5 animations:^
{
//animate in
}
completion:^ (BOOL finished)
{
//Optional
}];
}];

To fade out, you have to animate the alpha to 0, not to 1.
[UIView animateWithDuration:0.5 animations:^{_btn.alpha = 0.0;}];
This should work.

Related

infinitely scrolling background (UIView animation)

I'm trying to achieve an infinitely scrolling background by having two UIViews scroll and replace each other like a conveyor belt. This is my code so far, I can't seem to get it to work
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
bg1 = [[UIView alloc] initWithFrame:self.view.frame];
[bg1 setBackgroundColor:[UIColor redColor]];
bg2 = [[UIView alloc] initWithFrame:self.view.frame];
[bg2 setBackgroundColor:[UIColor blueColor]];
[self.view addSubview:bg1];
[self.view addSubview:bg2];
[self.view bringSubviewToFront:bg1];
[self animate];
}
- (void)animate {
[UIView animateWithDuration:3000 animations:^{
bg1.frame = CGRectOffset(bg1.frame, 0, bg1.frame.size.height);
}completion:^(BOOL done) {
if (done) {
bg1.frame = CGRectOffset(bg1.frame, 0, -bg1.frame.size.height);
[self.view sendSubviewToBack:bg1];
[UIView animateWithDuration:3000 animations:^{
bg2.frame = CGRectOffset(bg2.frame, 0, bg2.frame.size.height);
}completion:^(BOOL done) {
if (done) {
bg2.frame = CGRectOffset(bg2.frame, 0, -bg2.frame.size.height);
[self.view sendSubviewToBack:bg2];
[self animate];
}
}];
}
}];
}
my bad! i thought withDuration was in ms. It's in seconds!
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
bg1 = [[UIView alloc] initWithFrame:self.view.frame];
[bg1 setBackgroundColor:[UIColor redColor]];
bg2 = [[UIView alloc] initWithFrame:self.view.frame];
[bg2 setBackgroundColor:[UIColor blueColor]];
[self.view addSubview:bg1];
[self.view addSubview:bg2];
[self.view bringSubviewToFront:bg1];
[self animate];
}
- (void)animate {
[UIView animateWithDuration:3 animations:^{
bg1.frame = CGRectOffset(bg1.frame, 0, bg1.frame.size.height);
}completion:^(BOOL done) {
if (done) {
bg1.frame = CGRectOffset(bg1.frame, 0, -bg1.frame.size.height);
[self.view sendSubviewToBack:bg1];
[UIView animateWithDuration:3 animations:^{
bg2.frame = CGRectOffset(bg2.frame, 0, bg2.frame.size.height);
}completion:^(BOOL done) {
if (done) {
bg2.frame = CGRectOffset(bg2.frame, 0, -bg2.frame.size.height);
[self.view sendSubviewToBack:bg2];
[self animate];
}
}];
}
}];
}

How should I reload tableview content after switching containers.

I have a container view that can be switched between a tableview and a mapview when a user presses a UIButton. det determines which container view it is currently in.
- (IBAction)changer:(id)sender{
if(det == TRUE){
TableViewController *viewController2 = [[TableViewController alloc]init];
viewController2.view.frame = self.container.bounds;
[viewController2 willMoveToParentViewController:self];
[self.container addSubview:viewController2.view];
[self addChildViewController:viewController2];
[viewController2 didMoveToParentViewController:self];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.container cache:YES];
[UIView commitAnimations];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 55, 35)];
[button setImage:[UIImage imageNamed:#"mapSwitch.png"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(changer:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *back = [[UIBarButtonItem alloc] initWithCustomView:button];
[self.navigationItem setRightBarButtonItem:back];
det = FALSE;
}
else{
ViewController *viewController1 = [self.storyboard instantiateViewControllerWithIdentifier:#"vc1"];
viewController1.view.frame = self.container.bounds;
[viewController1 willMoveToParentViewController:self];
[self.container addSubview:viewController1.view];
[self addChildViewController:viewController1];
[viewController1 didMoveToParentViewController:self];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:1];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.container cache:YES];
[UIView commitAnimations];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 55, 35)];
[button setImage:[UIImage imageNamed:#"listSwitch.png"] forState:UIControlStateNormal];
[button addTarget:self action:#selector(changer:) forControlEvents:UIControlEventTouchUpInside];
UIBarButtonItem *back = [[UIBarButtonItem alloc] initWithCustomView:button];
[self.navigationItem setRightBarButtonItem:back];
det = TRUE;
}
}
The switching is just fine; it loads the tableview first which is populated correctly. Then, if you switch to the mapview, it is also fine. However, when I switch back to the table view and call a
[self.tableView reloadData];
method, the tableview is empty. Basically I have 2 arrays of info that need to be displayed on the tableview which return the correct information/content after switching back to the tableview, but do not appear in the tableview after reloaddata.
Is reloadData is not the best way to reload a tableview that was created before? I suspect that when the changer method reloads the tableview container, something is happening so there is nothing in the table view.
Or is there a way to "cache" the tableview so when you switch back to it, everything stays rather than reloading everything again?

How to create a flashing record button for iPhone

I've looked at several posts, including [this one].1 This is exactly what I want to do, but I cannot get it to work.
I want to show the user that they have pressed a record button, and that they will need to press it again to stop recording.
So far, the code for the start recording method looks like this:
NSLog(#"DetailVC - recordAudio - soundFilePath is %#", soundFile);
[audioRecorder prepareToRecord];
recording = YES;
NSLog(#"start recording");
NSLog(#"1");
//[autoCog startAnimating];
[audioRecorder recordForDuration:120];
recording = NO;
//Start a timer to animate the record images
if (recording == YES) {
toggle = FALSE;
timer = [NSTimer scheduledTimerWithTimeInterval: 2.0
target: self
selector: #selector(toggleButtonImage:)
userInfo: nil
repeats: YES];
//UIImage *changeImage = [UIImage imageNamed:stopButtonFile];
//[recordButton setImage:changeImage forState:UIControlStateNormal];
//[timer invalidate];
//timer = nil;
NSLog(#"2");
}
and the toggleButton method looks like this:
- (void)toggleButtonImage:(NSTimer*)timer
{
NSLog(#"%s", __FUNCTION__);
if(toggle)
{
NSLog(#"1");
/*
[UIView beginAnimations];
recordButton.opacity = 0.0;
[recordButton setAnimationDuration: 1.5];
[recordButton commitAnimations];
[recordButton setImage:[UIImage imageNamed:#"record.png"] forState: UIControlStateNormal];
*/
CGContextRef context = UIGraphicsGetCurrentContext();
[UIView beginAnimations:nil context:context];
[UIView setAnimationCurve:UIViewAnimationCurveEaseIn]; //delete "EaseOut", then push ESC to check out other animation styles
[UIView setAnimationDuration: 0.5];//how long the animation will take
[UIView setAnimationDelegate: self];
recordButton.alpha = 1.0; //1.0 to make it visible or 0.0 to make it invisible
[UIView commitAnimations];
}
else
{
NSLog(#"2");
CGContextRef context = UIGraphicsGetCurrentContext();
[UIView beginAnimations:nil context:context];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut]; //delete "EaseOut", then push ESC to check out other animation styles
[UIView setAnimationDuration: 0.5];//how long the animation will take
[UIView setAnimationDelegate: self];
recordButton.alpha = 0.0; //1.0 to make it visible or 0.0 to make it invisible
[UIView commitAnimations];
//[recordButton setImage:[UIImage imageNamed:#"stopGrey.png"] forState: UIControlStateNormal];
}
toggle = !toggle;
}
I get to see the logs showing that the loop is iterating, but:
the images do not switch, and
the operation is not running in parallel with the record method.
I would appreciate any ideas as to how to proceed.
Expanding on Ashley's answer, I'd go with something more like this:
- (IBAction)record:(id)sender {
self.recording = !self.recording;
if (!self.recording) {
[UIView animateWithDuration:0.1
delay:0.0
options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionBeginFromCurrentState
animations:^{
self.recordButton.alpha = 1.0f;
}
completion:^(BOOL finished){
}];
} else {
self.recordButton.alpha = 1.0f;
[UIView animateWithDuration:0.5
delay:0.0
options:UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse | UIViewAnimationOptionAllowUserInteraction
animations:^{
self.recordButton.alpha = 0.0f;
}
completion:^(BOOL finished){
}];
}
}
Try this:
- (IBAction)record:(id)sender
{
self.recording = !self.recording;
[self toggleButton];
}
- (void) toggleButton
{
if (!self.recording) {
self.recordButton.alpha = 1.0;
return;
}
[UIView animateWithDuration: 0.5
delay: 0.0
options: UIViewAnimationOptionCurveEaseInOut | UIViewAnimationOptionAllowUserInteraction
animations:^{
self.recordButton.alpha = !self.recordButton.alpha;
}
completion:^(BOOL finished) {
[self toggleButton];
}];
}

Keyboard behavior when forced open with inputAccessoryView?

I have a device connected to my iPad that is acting as an external keyboard, however, I still need a soft keyboard in my program. I have had some luck using the following article: Show iphone soft keyboard even thought a hardware keyboard is connected, but iOS 5 has broken this method. The bottom of the soft keyboard is slightly cut off in most views, but others only half the keyboard appears inside the window and not where you would expect it to.
All of the following code works in my AppDelegate.m file in iOS4, but not in iOS5.
forceKeyboard is called after UITextFieldTextDidBeginEditingNotification is sent.
-(void) textFieldBegan: (NSNotification *) theNotification
{
UITextField *theTextField = [theNotification object];
theTextField.inputAccessoryView = inputAccessoryView;
[self performSelector:#selector(forceKeyboard) withObject:nil afterDelay:0];
}
//Change the inputAccessoryView frame
-(void) forceKeyboard
{
inputAccessoryView.superview.frame = CGRectMake(0, 502, 1024, 265);
int movementDistance = 1;
float movementDuration = 0.3f;
[UIView beginAnimations: #"kb_anim_open" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
inputAccessoryView.superview.frame = CGRectOffset(inputAccessoryView.superview.frame, 0, movementDistance);
[UIView commitAnimations];
}
Close Keyboard is called after UITextFieldTextDidEndEditingNotification is sent.
-(void) textFieldEnd: (NSNotification *) theNotification
{
UITextView *theTextView = [theNotification object];
[theTextView resignFirstResponder];
[self performSelector:#selector(forceCloseKeyboard) withObject:nil afterDelay:0];
}
-(void) forceCloseKeyboard
{
inputAccessoryView.superview.frame = CGRectMake(0, 502, 1024, 265);
int movementDistance = 502;
float movementDuration = 0.3f;
[UIView beginAnimations: #"kb_anim_close" context: nil];
[UIView setAnimationBeginsFromCurrentState: YES];
[UIView setAnimationDuration: movementDuration];
inputAccessoryView.superview.frame = CGRectOffset(inputAccessoryView.superview.frame, 0, movementDistance);
[UIView commitAnimations];
}
Any ideas on how I can tame a soft keyboard would be greatly appreciated; I've tried wrestling with the superview.frame values for awhile but with no luck.
Thanks for reading.
UPDATE
I have figured out a setup that opens and closes the keyboard in iOS 4 and 5, but does not animate. Again, this is all in the AppDelegate where "textFieldBegan" and "textFieldEnd" are called by notifications sent when a user begins and ends editing respectively.
-(void) textFieldBegan: (NSNotification *) theNotification
{
UITextField *theTextField = [theNotification object];
if (!inputAccessoryView) {
inputAccessoryView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 1024, 1)];
}else{
inputAccessoryView.frame = CGRectMake(0, 0, 1024, 1);
}
theTextField.inputAccessoryView = inputAccessoryView;
[self performSelector:#selector(forceKeyboard) withObject:nil afterDelay:0];
}
-(void) textFieldEnd: (NSNotification *) theNotification
{
NSString *classstr = NSStringFromClass([[theNotification object] class]);
UITextView *theTextView = [theNotification object];
[self performSelector:#selector(forceCloseKeyboard) withObject:nil afterDelay:0];
[theTextView resignFirstResponder];
}
//Change the inputAccessoryView frame
-(void) forceKeyboard
{
//default center = 512, 591
inputAccessoryView.superview.frame = CGRectMake(0, 415, 1024, 353);
[UIView animateWithDuration:0.3 animations: ^ { [inputAccessoryView.superview transform]; }];
}
-(void) forceCloseKeyboard //Unnecessary?
{
inputAccessoryView.frame = CGRectMake(0, 0, 1024, 0);
[UIView animateWithDuration:0.3 animations: ^ { [inputAccessoryView transform]; }];
}
It looks as if the "forceCloseKeyboard" method isn't really doing anything as it looks like when the textField resigns responder it closes the keyboard anyway. I leave it here in case someone can come up with a way to animate the keyboard opening and closing.

How To Move UIImageView?

Heres the deal:
I code an UIImageView in the viewDidLoad and i want it to move down with my fonction buttonPressed** without creating an other subview like i do.
Heres the code.
-(void)viewDidLoad {
[super viewDidLoad];
banetteImage = [UIImage imageNamed:#"myBanette.png"];
UIImageView *banetteView = [[UIImageView alloc] initWithImage:banetteImage];
banetteView.frame = CGRectMake(100, -740, 568, 790);
banetteView.opaque = NO;
[NSTimer scheduledTimerWithTimeInterval:2.5 target:self selector:#selector(buttonPressed: ) userInfo:nil repeats:NO];
[self.view addSubview:banetteView];
}
-(void)buttonPressed {
double speed = 1 / round(random() % 100) + 1.0;
[UIView beginAnimations:nil context:banetteView];
[UIView setAnimationDuration: 2*speed ];
banetteView.frame = CGRectMake(100, -2, 568, 790);
banetteView.opaque = NO;
UIImageView *banetteView = [[UIImageView alloc] initWithImage:banetteImage];
banetteView2.frame = CGRectMake(100, -740, 568, 790);
banetteView.opaque = NO;
banetteView.hidden = YES;
[self.view addSubview:banetteView];
// set a stop callback so we can cleanup the banette when it reaches the
// end of its animation
[UIView setAnimationDidStopSelector:#selector(onAnimationComplete:finished:context:)];
[UIView setAnimationDelegate:self];
[UIView commitAnimations];
}
-(void)onAnimationComplete:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
UIImageView *banetteView = context;
double speed = 1 / round(random() % 100) + 1.0;
banetteView.frame = CGRectMake(100, -2, 568, 790);
banetteView2.opaque = NO;
[self.view addSubview:banetteView2];
[UIView beginAnimations:nil context:banetteView];
[UIView setAnimationDuration: 2*speed ];
[banetteView release];
}
I found by adapting this code
http://mobile.tutsplus.com/tutorials/iphone/iphone-sdk-learning-about-touch-events-basic-game-animation/

Resources