Objective-c animation block doesn't seem to fire - iphone

I have a method in my UIView subclass "Card" to dismiss an instance by fading its alpha from 1 to 0. I do a similar thing when I add the card to the superview and it fades in fine. But when I call fadeAway, it just disappears immediately. The presentation code is in my controller class. Here is my Card.h and Card.m
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#class Card;
#interface Card : UIView {
int upperOperand;
int lowerOperand;
NSString* theOperator;
int theResult;
}
#property(nonatomic) int upperOperand;
#property(nonatomic) int lowerOperand;
#property(nonatomic, retain) NSString* theOperator;
#property(nonatomic) int theResult;
- (void)fadeAway;
#end
#import "Card.h"
#implementation Card
#synthesize upperOperand;
#synthesize lowerOperand;
#synthesize theOperator;
#synthesize theResult;
- (void)fadeAway {
self.alpha = 1.0f;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:2.0f];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
self.alpha = 0.0f;
[UIView commitAnimations];
[self removeFromSuperview];
}
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
// Initialization code
self.backgroundColor = [UIColor redColor];
self.layer.cornerRadius = 15;
self.alpha = 1.0;
self.layer.borderColor = [[UIColor blueColor] CGColor];
self.layer.borderWidth = 4;
}
return self;
- (void)dealloc {
[super dealloc];
}
#end

Since you're removing self from its superview immediately, I don't think it ever has a chance to perform the animation.
You might want to look into setAnimationDidStopSelector:. There's a discussion on this here: Animation End Callback for CALayer?
Another idea is to delay the removal of the subview. For example,
[self performSelector:#selector(removeFromSuperview)
withObject:nil
afterDelay:2.0f];

Related

Buttons displaced/distorted when hiding the navigation bar (After Rotation)

My application has two ViewControllers linked with NavigationController. The First NavigationController has one view with buttons and one view with labels. This view is a circular rotating menu and it represents my home page. The views can rotate with CGAffineTransformMakeRotation - QuartzCore (apparently it's causing the issue) on touchesMoved:.
I wanted to hide the NavigationBar only in this view, so I used setNavigationBarHidden:YES on ViewWillAppear. Then show the bar on ViewWillDisappear.
On the simulator, everything works as expected until i rotate the first ViewController, when i rotate then click on any button (go to the second ViewController) then click on Back (to go back to my first ViewController), everything will be distorted!.
I tried to fix the issue by adding [self.view setBounds:[[UIScreen
mainScreen]bounds]]; *[self.view setFrame:[[UIScreen
mainScreen]bounds]];* in ViewDidLoad method or ViweWillAppear,
the issue remains.
I tried to set NavigationBar alpha to 0 in ViewWillAppear and set
it to 1 on ViewWillDisappear and I tried
self.navigationController.navigationBar.translucent = YES both
options didn't resolve the problem.
I tried to set programmatically views, buttons and labels positions
in ViewWillAppear and it doesn't resolve the problem.
I doubted the animation so I removed it but it hasn't any effect on the problem.
As a beginner I'm unable to resolve this issue, please help!
ViewController.h (first ViewController)
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#interface ViewController : UIViewController
#property (nonatomic, strong) IBOutlet UIView *aView;
#property (nonatomic, strong) IBOutlet UIView *bView;
#property (nonatomic, strong) IBOutlet UIButton *bimg1;
…
#property (strong, nonatomic) IBOutlet UILabel *label1;
…
-(void) rotateTo:(CGFloat)x andY:(CGFloat)y;
#end
ViewController.m
#import "ViewController.h"
#implementation ViewController
#synthesize aView = _aView;
…
#synthesize bimg1 = _bimg1;
…
#synthesize label1 = _label1;
…
static inline double toradians (double degrees) {
return degrees * M_PI/180;
}
-(void)viewDidLoad {
![enter image description here][1][super viewDidLoad];
//Set text font
[_label1 setFont:[UIFont fontWithName:#"Consolas" size:16]];
…
[self.view setBounds:[[UIScreen mainScreen]bounds]];
[self.view setFrame:[[UIScreen mainScreen]bounds]];
}
-(void)viewWillAppear:(BOOL)animated {
self.navigationController.navigationBar.hidden = YES;
printf("Aview x: %f | Aview y: %f \n",self.aView.frame.origin.x, self.aView.frame.origin.y);
printf("Aview width: %f | Aview height: %f \n",self.aView.frame.size.width, self.aView.frame.size.height);
}
-(void)viewWillDisappear:(BOOL)animated {
self.navigationController.navigationBar.hidden = NO;
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
CGPoint LastTouchPoint = [touch locationInView:self.view];
CGFloat LasTouchx = LastTouchPoint.x;
CGFloat LasTouchy = LastTouchPoint.y;
CGPoint CenterPoint = self.view.center;
CGFloat x = LasTouchx - CenterPoint.x;
[self rotateTo:x andY:y];
}
-(void) rotateTo:(CGFloat)x andY:(CGFloat)y {
CGFloat angle = x/y;
angle = atan(angle);
angle = angle * 360/M_PI;
angle *= 0.0174532925;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDelegate:self];
[UIView setAnimationCurve:UIViewAnimationCurveEaseOut];
[UIView setAnimationDuration:1];
self.aView.transform=CGAffineTransformMakeRotation(-angle);
self.bView.transform=CGAffineTransformMakeRotation(-angle);
self.bimg1.transform=CGAffineTransformMakeRotation(angle);
self.bimg2.transform=CGAffineTransformMakeRotation(angle);
self.bimg3.transform=CGAffineTransformMakeRotation(angle);
self.bimg4.transform=CGAffineTransformMakeRotation(angle);
self.label1.transform=CGAffineTransformMakeRotation(angle);
self.label2.transform=CGAffineTransformMakeRotation(angle);
self.label3.transform=CGAffineTransformMakeRotation(angle);
self.label4.transform=CGAffineTransformMakeRotation(angle);
[UIView commitAnimations];
}
- (void)viewDidUnload
{
[self setBimg1:nil];
…
[self setAView:nil];
[self setBView:nil];
[super viewDidUnload];
}
Yeah, I figured out the problem… The autoresize of the main View was squeezing my subviews when the NavigationController is hidden or not. so i added self.view.autoresizesSubviews = NO; to ViewDidLoad and the problem is fixed.

How to scroll view up when keyboard appears?

I know that this question has been asked over and over again, but nothing seems to be working for me. Most of the solutions around are pretty out of date, and the rest are incredibly huge blocks of code that are ten times larger then the actual projects coding. I have a few UITextFields lined up vertically, but when the keyboard launches to edit one, it covers up the text field. I was wondering if there is a simple beginner way to scroll the view up, and then back down when the editing starts and ends?
Thank you.
I have made solutions that work with scroll and non-scroll views using keyboard notification and a detection of the current first responder, but sometimes I use this trivial solution instead: The simple way is to detect the opening keyboard via the text field delegate's textViewDidBeginEditing: method and to move the entire view up. The easiest way to do this is with something along the lines of changing self.view.bounds.origin.y to -100 (or whatever). Use the corresponding textViewShouldEndEditing: method to set it to the opposite, which is 100 in this case. Changing bounds is a relative procedure. After changing it the frame is moved but the bounds origin is still zero.
Since I found it, I use TPKeyboardAvoiding - https://github.com/michaeltyson/TPKeyboardAvoiding.
It is working great, and is very easy to setup:
Add a UIScrollView into your view controller's xib
Set the scroll view's class to TPKeyboardAvoidingScrollView (still in the xib, via the identity inspector)
Place all your controls within that scroll view
You can also create it programmatically, if you want.
There is a class for the same need inside a UITableViewController ; it is only needed in case you support a version of iOS below 4.3.
#BenLu and other users who are facing problem of the function are never getting called is because of following reason:
As the delegate inbuild function bydefaults return void instead of BOOL this is how it should be as follows:
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.35f];
CGRect frame = self.view.frame;
frame.origin.y = -100;
[self.view setFrame:frame];
[UIView commitAnimations];
}
-(void)textFieldDidEndEditing:(UITextField *)textField
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.35f];
CGRect frame = self.view.frame;
frame.origin.y = 100;
[self.view setFrame:frame];
[UIView commitAnimations];
}
I spent sometime on this problem and gathered pieces code to create one final solution. My problem was related to UITableView scrolling and keyboard open/close.
You need two partial methods in your cell class:
void EditingBegin(UITextField sender)
{
// Height of tallest cell, you can ignore this!
float tableMargin = 70.0f;
float tableHeight = _tableView.Frame.Size.Height;
float keyBoardHeight = KeyboardHeight();
NSIndexPath[] paths = this._tableView.IndexPathsForVisibleRows;
RectangleF rectLast = this._tableView.RectForSection(paths[paths.Length - 1].Section);
RectangleF rectFirst = this._tableView.RectForSection(paths[0].Section);
float lastCellY = rectLast.Y - rectFirst.Y;
if (lastCellY > tableHeight - keyBoardHeight)
{
float diff = lastCellY - (tableHeight - tableMargin - keyBoardHeight);
this._tableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, diff, 0.0f);
}
float cellPosition = this._tableView.RectForSection(this._section).Y;
if (cellPosition > tableHeight - keyBoardHeight)
{
if (this._tableView.ContentInset.Bottom == 0.0f)
{
float diff = cellPosition - (tableHeight - tableMargin - keyBoardHeight);
this._tableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, diff, 0.0f);
}
else
{
this._tableView.ScrollToRow(NSIndexPath.FromItemSection(0, this._section), UITableViewScrollPosition.Middle, true);
}
}
}
partial void EditingEnd(UITextField sender)
{
UIView.BeginAnimations(null);
UIView.SetAnimationDuration(0.3f);
this._tableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, 0.0f, 0.0f);
UIView.CommitAnimations();
}
and then in your view controller class:
public override void WillAnimateRotation(UIInterfaceOrientation toInterfaceOrientation, double duration)
{
base.WillAnimateRotation(toInterfaceOrientation, duration);
float bottom = this.TableView.ContentInset.Bottom;
if (bottom > 0.0f)
{
if (toInterfaceOrientation == UIInterfaceOrientation.Portrait || toInterfaceOrientation == UIInterfaceOrientation.PortraitUpsideDown)
{
bottom = bottom * UIScreen.MainScreen.Bounds.Width / UIScreen.MainScreen.Bounds.Height;
}
else
{
bottom = bottom * UIScreen.MainScreen.Bounds.Height / UIScreen.MainScreen.Bounds.Width;
}
UIEdgeInsets insets = this.TableView.ContentInset;
this.TableView.ContentInset = new UIEdgeInsets(0.0f, 0.0f, bottom, 0.0f);
}
}
If you have a UITableView or a UIScrollView it's better to change values for contentOffset instead of making changes to the frame.
Working on Peter's Answer, adding this method to your class works nicely:
- (void)textViewDidBeginEditing:(UITextField *)textField {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.35f];
CGPoint offset = self.tableView.contentOffset;
offset.y += 200; // You can change this, but 200 doesn't create any problems
[self.tableView setContentOffset:offset];
[UIView commitAnimations];
}
That's it, no need to add the textViewDidEndEditing method.
I shouldn't need to say this, but for this to work your UITextField or UITextView must be a delegate of your controller.
Starting with Peter's answer, I developed the following approach in Swift 3.0 under iOS 10.1. I'm doing this for a textView, so I have implemented the UITextViewDelegate functions textViewDidBeginEditing and textViewDidEndEditing where I adjust the view's bounds. As you can see, I set the origin Y value to a small positive number to scroll up and then back to 0 to return to the original position.
Here is the relevant code from my ViewController. You don't need to animate, but it adds a nice touch.
func textViewDidBeginEditing(_ textView: UITextView)
{
if UIScreen.main.bounds.height < 568 {
UIView.animate(withDuration: 0.75, animations: {
self.view.bounds.origin.y = 60
})
}
}
func textViewDidEndEditing(_ textView: UITextView)
{
if UIScreen.main.bounds.height < 568 {
UIView.animate(withDuration: 0.75, animations: {
self.view.bounds.origin.y = 0
})
}
}
i have a scrollview and 3 text fields in this. I have a simple code from my own application :
.h file is :
#import <UIKit/UIKit.h>
#interface AddContactViewController : UIViewController<UITextFieldDelegate, UIScrollViewDelegate>
#property (nonatomic, retain) NSDictionary *dict_contactDetail;
#property (nonatomic, retain) IBOutlet UILabel *lbl_name;
#property (nonatomic, retain) IBOutlet UITextField *txtField_tel;
#property (nonatomic, retain) IBOutlet UITextField *txtField_address;
#property (nonatomic, retain) IBOutlet UITextField *txtField_email;
#property (nonatomic, retain) IBOutlet UIScrollView *scrollView;
#end
.m file :
#import "AddContactViewController.h"
#interface AddContactViewController ()
#end
#implementation AddContactViewController
#synthesize dict_contactDetail;
#synthesize lbl_name, txtField_tel, txtField_email, txtField_address, scrollView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
// NSLog(#"dict_contactDetail : %#", dict_contactDetail);
UIBarButtonItem * rightButton = [[UIBarButtonItem alloc] initWithTitle:#"Add" style:UIBarButtonSystemItemDone target:self action:#selector(addEmergencyContact:)];
self.navigationItem.rightBarButtonItem = rightButton;
lbl_name.text = [NSString stringWithFormat:#"%# %#", [dict_contactDetail valueForKey:#"fname"], [dict_contactDetail valueForKey:#"lname"]];
txtField_tel.returnKeyType = UIReturnKeyDone;
txtField_email.returnKeyType = UIReturnKeyDone;
txtField_address.returnKeyType = UIReturnKeyDone;
}
-(void)addEmergencyContact:(id)sender
{
scrollView.frame = CGRectMake(0, 0, 320, 460);
}
#pragma mark - text field delegates
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
if([textField isEqual:txtField_tel])
{
[scrollView setContentOffset:CGPointMake(0, 70)];
scrollView.frame = CGRectMake(0, 0, 320, 210);
}
if([textField isEqual:txtField_address])
{
[scrollView setContentOffset:CGPointMake(0, 140)];
scrollView.frame = CGRectMake(0, 0, 320, 210);
}
if([textField isEqual:txtField_email])
{
[scrollView setContentOffset:CGPointMake(0, 210)];
scrollView.frame = CGRectMake(0, 0, 320, 210);
}
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
scrollView.frame = CGRectMake(0, 0, 320, 460);
[textField resignFirstResponder];
return YES;
}
#end

Objective-c Hidden View animation

Hello I have a hidden view inside of my view that appears by the click of a button. But when you click on the button I want the view to do an slide up animation so it won't just appear but slide up to it's position.
Here is the code for my hidden view:
in .h:
#interface hidden_viewsViewController : UIViewController {
IBOutlet UIView *loginview;
}
#property (nonatomic, retain) IBOutlet UIView *loginview;
- (IBAction)login;
- (IBAction)logout;
And in .m
#synthesize loginview;
- (IBAction)login {
loginview.hidden = NO;
}
- (IBAction)logout {
loginview.hidden = YES;
}
- (void)viewDidLoad {
[super viewDidLoad];
loginview.hidden = YES;
}
Try, assuming the view is in portrait orientation:
- (IBAction)login {
[self.view bringSubviewToFront:loginView];
loginview.frame = CGRectMake(0, 480, 320, 480);
loginview.hidden = NO;
[UIView animateWithDuration:1.0
animations:^{
loginview.frame = CGRectMake(0, 0, 320, 480);
}];
}
you should change the frame property of your view, and you should do it within an animations block, as follows:
-(IBAction)login
{
[UIView beginAnimations:#"showView" context:nil];
[UIView setAnimationDuration:0.5];
CGRect viewNewFrame = self.view.frame;
viewNewFrame.origin.y = 0;
self.view.frame = viewNewFrame;
[UIView commitAnimations];
}
Hope it helps!

change position of imageview with animation

i want to change position of imageview with animation. it just like draw playing card and it will sets to center anyone here who help me for this.
Code-:
#interface PockerAppViewController : UIViewController
{
UIButton *btn;
UIImageView *cards;
}
#property(nonatomic,retain) IBOutlet UIButton *btn;
#property(nonatomic,retain) IBOutlet UIImageView *cards;
-(IBAction)hidebtn:(id)sender;
-(void)setCards;
#end
--------------------------------.mfile-----------------------------
#implementation PockerAppViewController
#synthesize btn,cards;
/*
// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
{
// Custom initialization
}
return self;
}
// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
[super viewDidLoad];
cards = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"King.png"]];
//[cards setHidden:TRUE];
}
-(IBAction)hidebtn:(id)sender
{
[btn setHidden:TRUE];
[self setCards];
}
-(void)setCards
{
[cards setFrame:cards.frame];
[UIView beginAnimations:#"Move" context:nil];
[UIView setAnimationDuration:0.3];
[cards setCenter:CGPointMake(60,240)];
[UIView commitAnimations];
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
CGPoint pos = [touch locationInView:touch.view];
NSLog(#"X: %f",pos.x);
NSLog(#"X: %f",pos.y)
}
- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}
- (void)viewDidUnload {
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void)dealloc {
[super dealloc];
}
this is my data it help me to solve this problem..
Try something like this:
[URImageView setFrame:CurrentPositionFrame];
[UIView beginAnimations:#"animateTableView" context:nil];
[UIView setAnimationDuration:0.4];
[URImageView setFrame:ToTheNewPositionFrame];
[UIView commitAnimations];
As Till pointed you can also use the Center property:
[UIView beginAnimations:#"animateTableView" context:nil];
[UIView setAnimationDuration:0.4];
[URImageView setCenter:CGPointMake(nPositionX ,nPositionY)];
[UIView commitAnimations];
Thanks Till.
think this could be helpful
http://www.flashgamehole.com/Tong/play-game/en/

How can I show a sequence of buttons highlighting?

Similar to the Simon games of old, I want to show the user a button sequence & then have them repeat it back. The place I'm stuck is showing the first button highlighted for, say, 500ms, waiting 100ms, showing the second highlighted for 500ms, waiting another 100ms, showing the 3rd & so on.
From other Stackoverflower'ers I've gotten to this block:
redButton.highlighted = YES;
[UIView beginAnimations:#"" context:nil];
[UIView setAnimationStartDate:[NSDate dateWithTimeIntervalSinceNow:1]];
[UIView setAnimationsEnabled:NO];
redButton.highlighted = NO;
[UIView commitAnimations];
[UIView beginAnimations:#"" context:nil];
[UIView setAnimationStartDate: [NSDate dateWithTimeIntervalSinceNow:2]];
[UIView setAnimationsEnabled:NO];
blueButton.highlighted = YES;
[UIView commitAnimations];
The redButton will highlight, but none of the subsequent actions take place.
There might be a way to do this with Core Animation, but it is not necessary. You are not animating the highlighted property, you are just switching it on and off.
I created a simple view-based iPhone application to do this with timers. Here is the code from the view controller:
SimonTestViewController.h:
#import <UIKit/UIKit.h>
#interface SimonTestViewController : UIViewController {
IBOutlet UIButton *redButton;
IBOutlet UIButton *blueButton;
IBOutlet UIButton *greenButton;
IBOutlet UIButton *yellowButton;
}
- (void)highlightButton:(UIButton*)button Delay:(double)delay;
- (void)highlightOn:(NSTimer*)timer;
- (void)highlightOff:(NSTimer*)timer;
#end
SimonTestViewController.m:
#import "SimonTestViewController.h"
#implementation SimonTestViewController
const double HIGHLIGHT_SECONDS = 0.5; // 500 ms
const double NEXT_SECONDS = 0.6; // 600 ms
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self highlightButton:redButton Delay:0.0];
[self highlightButton:blueButton Delay:NEXT_SECONDS];
[self highlightButton:greenButton Delay:NEXT_SECONDS * 2];
[self highlightButton:blueButton Delay:NEXT_SECONDS * 3];
[self highlightButton:yellowButton Delay:NEXT_SECONDS * 4];
[self highlightButton:redButton Delay:NEXT_SECONDS * 5];
}
- (void)highlightButton:(UIButton*)button Delay:(double)delay {
[NSTimer scheduledTimerWithTimeInterval:delay target:self selector:#selector(highlightOn:) userInfo:button repeats:NO];
}
- (void)highlightOn:(NSTimer*)timer {
UIButton *button = (UIButton*)[timer userInfo];
button.highlighted = YES;
[NSTimer scheduledTimerWithTimeInterval:HIGHLIGHT_SECONDS target:self selector:#selector(highlightOff:) userInfo:button repeats:NO];
}
- (void)highlightOff:(NSTimer*)timer {
UIButton *button = (UIButton*)[timer userInfo];
button.highlighted = NO;
}