iOS: Animating text position of UIButton doesn't work - ios

I want to have the text of the button 'go away' when pressing a 'wrong answer' button.
In my problem-demo code, my project has two buttons, one with outlet 'myBtn' without any action, and one with TouchUpInside action. The action handler looks like this:
- (IBAction)goPressed:(UIButton*)sender {
//UILabel *lbl = self.myBtn.titleLabel;
UILabel *lbl = sender.titleLabel;
[UIView animateWithDuration:1.0
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
lbl.center = CGPointMake(lbl.center.x-60, lbl.center.y);
lbl.alpha = 0;
}
completion:nil];
}
I am trying to animate two properties: 'alpha' to go from 1 to 0, and position of text to move 60 points to the left.
If I uncomment the first "UILAbel" line and comment the second, then pressing the button runs a nice animation in the second button.
But if I leave the code as it appears, trying to animate the text of the pressed button itself, the alpha is animating fine, but the position is not changing.
Any help would be highly appreciated!

I have seen this kind of problem occurring on iOS7. Animations that worked fine inside an IBAction, don't work on iOS7. I had to move all my animation code to a different method and call the selector after a delay. Your code will work fine if you do this -
- (IBAction) goPressed:(UIButton*)sender {
[self performSelector:#selector(animateButton:) withObject:sender afterDelay:0.1];
}
- (void) animateButton:(UIButton *) button{
UILabel *lbl = button.titleLabel;
[UIView animateWithDuration:1.0
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
lbl.center = CGPointMake(lbl.center.x-60, lbl.center.y);
lbl.alpha = 0;
}
completion:nil];
}

Your problem is mixing up the UIButton with the UILabel.
The method parameter (UIButton*)sender is referencing a UIButton in this case. The reason UILabel *lbl = sender.titleLabel; doesn't work is because the sender is a UIButton reference. To access the label object, you must reference the the UILabel embedded in the UIButton via the hirarchy sender > UIButton > UILabel.
So the code you should use is:
UIButton *button = sender;
UILabel *lbl = sender.titleLabel;
[UIView animateWithDuration:1.0
delay:0.0
options:UIViewAnimationOptionCurveEaseOut
animations:^{
lbl.center = CGPointMake(lbl.center.x-60, lbl.center.y);
lbl.alpha = 0;
}
completion:nil];
}
The reason why the code as it appears behaves strangly is because alpha is a property of both UIButtons and UILabels. So it will work even if you are incorrectly refenrencing the sender.

Related

Animating a UIButton to fullscreen

so I have a very simple button that when clicked goes to fullscreen and when clicked again goes back to the same position it was initially in. For some reason it works perfectly without the animation. When I uncomment the animation part when I initially click the button it does nothing, the second time I click it slightly enlarges. The third time I click it animates slowly but back to it's smaller original size... Why is it animating the opposite way?
- (IBAction)viewImage1:(id)sender {
UIButton *btn = (UIButton*) sender;
if (btn.tag == 0)
{
CGRect r = [[UIScreen mainScreen] bounds];
/*[UIView animateWithDuration:0.5f delay:0.0f options:0 animations:^{*/
[sender setFrame: r];
/*}completion:nil];*/
btn.tag = 1;
}
else
{
btn.tag = 0;
[sender setFrame:CGRectMake(0,0,370,200)];
}
}
There are two solutions to your problem either of which will work:
Disable Autolayout. (discouraged)
You can do that in Interface Builder by opening the File Inspector
in the right pane and unchecking the respective check box.
However, if you want to use Autolayout for constraining other UI elements in your view (which is quite a good idea in most cases) this approach won't work which is why I would recommend the second solution:
Keep Autolayout enabled, create an outlet for your button in your view controller and set
self.myButton.translatesAutoresizingMaskIntoConstraints = YES;
in your view controller's viewDidLoad method.
You could also add layout constraints to your button and animate those. (This excellent Stackoverflow post explains how it's done.)
The reason for this tricky behavior is that once you enable Autolayout a view's frame is no longer relevant to the actual layout that appears on screen, only the view's layout constraints matter. Setting its translatesAutoresizingMaskIntoConstraints property to YES causes the system to automatically create layout constraints for your view that will "emulate" the frame you set, in a manner of speaking.
It is easier to do this with auto layout and constraints. Create an IBOutlet for the height constraint of your button call it something like btnHeight. Do the same for the width constraint call it something like btnWidth. Then create an IBAction like so:
- (IBAction)buttonPress:(UIButton *)sender {
UIButton *btn = (UIButton *) sender;
CGRect r = [[UIScreen mainScreen] bounds];
if (CGRectEqualToRect(btn.frame, CGRectMake(0.0, 0.0, 370, 200))) {
[UIView animateWithDuration:0.5 delay:0.0 options:0 animations:^{
self.btnHeight.constant = r.size.height;
self.btnWidth.constant = r.size.width;
[self.view layoutIfNeeded];
} completion:^(BOOL finished){
}];
}else{
[UIView animateWithDuration:0.5 delay:0.0 options:0 animations:^{
self.btnHeight.constant = 200.0;
self.btnWidth.constant = 370.0;
[self.view layoutIfNeeded];
} completion:^(BOOL finished){
}];
}
}
In my experience animating the frame of a UIButton does not work well, a, the only method, I'm aware of, is to use CGAffineTransformScale which will rasterize the title of the button and scale it as well.

UITextField hidden while keyboard is showing

In my app I've this login screen:
Above the first test field I've an image, the configuration in Interface Builder is the follow:
Now when I tap on the UITextField they should move up otherwise in iPhone 4/4s the field will be covered by keyboard.
Now I'm using the following code:
-(void)textFieldDidBeginEditing:(UITextField *)textField {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.35f];
CGRect frameView = self.view.frame;
CGRect frameImage = self.imageViewLogo.frame;
CGRect frameTextFieldUsername = self.textFieldUsername.frame;
CGRect frameTextFieldPassword = self.textFieldPassword.frame;
CGRect frameButtonLogin = self.buttonLogin.frame;
frameView.origin.y = -100;
frameImage.origin.y = -100;
frameTextFieldUsername.origin.y = -100;
frameTextFieldPassword.origin.y = -100;
frameButtonLogin.origin.y = -100;
[self.view setFrame:frameView];
[self.imageViewLogo setFrame:frameImage];
[self.textFieldUsername setFrame:frameTextFieldUsername];
[self.textFieldPassword setFrame:frameTextFieldPassword];
[self.buttonLogin setFrame:frameButtonLogin];
[UIView commitAnimations];
}
When I try to run the app in simulator or on a real device the view scrolls up of 100 but the image, the text fields and button doesn't scrolls up... I thought that the problem depend on the constraints, can you help me to fix this issue?
Thank you
The way in which you are trying to do this will get you in trouble. As you are giving hardcoded values of frame.
Try to use keyboard avoiding library it's the better and safer way of doing it.
-(void)textFieldDidBeginEditing:(UITextField *)textField {
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.35f];
CGRect frameView = self.view.frame;
CGRect frameImage = self.imageViewLogo.frame;
CGRect frameTextFieldUsername = self.textFieldUsername.frame;
CGRect frameTextFieldPassword = self.textFieldPassword.frame;
CGRect frameButtonLogin = self.buttonLogin.frame;
frameView.origin.y = -100;
// no need of changing frames of TextFields inside the View, Just change the y-padding of View
[self.view setFrame:frameView];
[UIView commitAnimations];
}
reduce the y-padding to -120 and check
Hope this helps thanks
If your views are set up to use AutoLayout, changing frame will do nothing.
You should subscribe to UIKeyboardWillChangeFrameNotification and perform your changes there. In case of constraints you would update the constrains constants here and the call -setNeedsUpdateConstraints on the superview.
You have to figure out if the keyboards is appearing or disappearing at all if you want to support external keyboard.
Otherwise you can listen for UIKeyboardWillShowNotification and UIKeyboardWillHideNotification
For auto up the textFields while keyboard comes not need to use the thirdParty Classes.
Create a static tableView and design each textFields and button in each static cells.
TableView automatically handle the auto up textFields while keyboard comes.
Hi the simple and easy trick for doing it is :-
Take outlet of top constraint of username or email id textfield in your class and on textfield did begin editing delegate decrease the constraint's constant value so it will goes up when u select the textfield and at textField did end editing delegate again set constraint's constant value to previous one so it will reset on previous position.
eg:-Assuming you set Top Constraint value in Storyboard is 150
-(void)textFieldDidBeginEditing:(UITextField *)textField {
_topConstraint.constant = 10.00;
[UIView animateWithDuration:0.5f animations:^{
[self.view layoutIfNeeded];
}];
}
-(void)textFieldDidEndEditing:(UITextField *)textField {
_topConstraint.constant = 150.00;
[UIView animateWithDuration:0.5f animations:^{
[self.view layoutIfNeeded];
}];
}
Hope it will help you.

Showing UIImageView on startup after a delay with close button

I want to show a UIImageView after 3 seconds from the view did load. This image view is kind of a static Ad, a static image loaded that will show up when the application starts as mentioned. This ismageView should have a close button on it so the user can close it just like the typical ad behavior. It's my first time dealing with this kind of situations so please help me out i'm totally lost.
Till now i got to animate a view containing an image view with fade in and out animations, which is perfect..but now haw can i add a close button to it, to make her dismiss only when that button is pressed? this is my code
UIImageView *wnn = [[UIImageView alloc]init];
wnn.frame = CGRectMake(100, 100, 300, 300);
[wnn setImage:[UIImage imageNamed:#"menu-icon.png"]];
UIView *jn = [[UIView alloc]init];
[jn addSubview:wnn];
[self.navigationController.view addSubview: jn];
[jn setAlpha:0.f];
[UIView animateWithDuration:2.f delay:0.f options:UIViewAnimationOptionCurveEaseIn animations:^{
[jn setAlpha:1.f];
} completion:^(BOOL finished) {
[UIView animateWithDuration:2.f delay:0.f options:UIViewAnimationOptionCurveEaseInOut animations:^{
[jn setAlpha:0.f];
} completion:nil];
}];
You can follow below steps:
Open Storyboard file with your viewcontroller.
Place UIView from library to your main view of viewcontroller.
Place your image and close button on new UIview placed.
Now set IBOutlet for this uiview.
Make hide/show this view instead of image and close button in your method.

IOS - buttons slide in from right side animation

i am new to IOS programming. i have a background image on my screen. What i want is when app launches screen shows with the background image and then after 1 sec 2 buttons comes up from right side of the screen. how can i do this. here is the image what i am trying to do
button 1 and button2 have to be invisible first. after 1 second they comes up from right side.
if there are any tutorials related to this kind of animation then please share
You can use simple UIView Animations to achieve this.
Set your button x origin any value greater than screen size so that it is not visible first. Then reset the button frame to a visible value with view animation. For example call the following function in your viewWillAppear: method.
- (void) animateButton {
// Setting button origin to value greater than the view width.
CGRect frame = button.frame;
frame.origin.x = self.view.frame.size.width+10;// or set any value > 320
button.frame = frame;
[UIView animateWithDuration:0.5
delay:2.0
options: UIViewAnimationCurveEaseOut
animations:^{
button.frame = CGRectMake(20, 100, 60, 25) ;// Any value according to your requirement
}
completion:^(BOOL finished){
NSLog(#"Done!");
}];
}
Refer Tutorial
You can do it this way, please note that, if you want to animate the way your button shows up, you must hide them using alpha = 0.0f (and not hidden = true). This way, you will have a smooth showing up animation !
Here it is :
First, on your viewDidLoad of your UIViewController, you have to set up a NSTimer of 1sec, then let it call the method that will let your buttons appear :
- (void) viewDidLoad {
[super viewDidLoad];
// Do your init stuff here
// We will call your buttons as if they are declared as properties of your class, ask if you don't know how to set them
self.button1.alpha = 0.0f;
self.button2.alpha = 0.0f;
// This will wait 1 sec until calling showButtons, where we will do the trick
NSTimeInterval timeInterval = 1.0;
[NSTimer scheduledTimerWithTimeInterval:timeInterval target:self selector:#selector(showButtons) userInfo:nil repeats:NO];
}
- (void) showButtons {
[UIView beginAnimations:#"buttonShowUp" context:nil];
[UIView setAnimationDuration:0.5]; // Set it as you want, it's the length of your animation
self.button1.alpha = 1.0f;
self.button2.alpha = 1.0f;
// If you want to move them from right to left, here is how we gonna do it :
float move = 100.0f; // Set it the way you want it
self.button1.frame = CGRectMake(self.button1.frame.origin.x - move,
self.button1.frame.origin.y,
self.button1.frame.size.width,
self.button1.frame.size.height);
self.button2.frame = CGRectMake(self.button2.frame.origin.x - move,
self.button2.frame.origin.y,
self.button2.frame.size.width,
self.button2.frame.size.height);
// If you want to set them in the exact center of your view, you can replace
// self.button1.frame.origin.x - move
// by the following
// (self.view.center - self.button1.frame.size.width/2)
// This way, your button will be centered horizontally
[UIView commitAnimations];
}
Ask if you have any questions !
Set the buttons' x co-ordinates such that the button is just outside the screen on the right side.
And then try the following in your viewDidLoad()
[UIView animateWithDuration:0.5
delay:1.0
options:NO
animations:^{ change your button x co- ordinate here to the co-ordinate you need it on finally}
completion:NULL];

Animate UIButton changes location on text change

I'm having trouble changing my button text after animation.
Defined in my .h file
#property (weak, nonatomic) IBOutlet UIButton *btnCheck;
I call this method when i want to animate the button location change
- (void)updateViews {
if(checkedIn){
[UIView animateWithDuration:0.3f
delay:0.0f
options:UIViewAnimationOptionTransitionNone
animations:^{
btnClear.hidden = YES;
[btnCheck setFrame:CGRectMake(90, btnCheck.frame.origin.y, btnCheck.frame.size.width, btnCheck.frame.size.height)];
}
completion:nil];
}else{
[UIView animateWithDuration:0.3f
delay:0.0f
options:UIViewAnimationOptionTransitionNone
animations:^{
[btnCheck setFrame:CGRectMake(20, btnCheck.frame.origin.y, btnCheck.frame.size.width, btnCheck.frame.size.height)];
}
completion:^(BOOL finished){
btnClear.hidden = NO;
}];
}
checkedIn = !checkedIn;
}
That works perfect, pics included below for reference:
The problem is as soon as i try change the name of the button it jumps back to its original frame.
I change the button text in another method like this,
btnCheck.titleLabel.text = #"test";
And as soon as i change that the button jumps back
What's causing the button frame to be reset?
I've tried changing it before the animation,during and on completion. It animates to the new location and jumps back.
This will probabily not answer your question, but I'll show you a better way to change a frame when you want to change only one property in your frame
CGRect buttonFrame = [btnCheck frame];
buttonFrame.origin.x = newXOrigin;
[UIView animateWithDuration:0.3f
animations:^{
[btnCheck setFrame:buttonFrame];
}];
I prefer this method, because you don't have to create a new CGRect and copy paste all the unmodified frame attributes. Ow and you might wanna get the hidden assignment out of the animation block, since that cannot be animated
You should not change UIButton's title that way. Instead, try setting it's title using setTitle:forState: method. Try this, and let me know if this was helpful, Good Luck!
It was Autolayout that caused the problem. Disabled that and everything worked

Resources