This question already has answers here:
How to stop unwanted UIButton animation on title change?
(24 answers)
Closed 4 months ago.
I am animating a view that is sliding down. In the view there is a simple UIButton. The view and the button have fixed widths and heights (I checked with adding a color as background). Although when use:
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
//Slide Down the notification
CGRect notificationsRect = self.notificationContainerView.bounds;
notificationsRect.origin.y = 0;
notificationViewController.view.frame = notificationsRect;
} completion:^(BOOL finished) {
[notificationViewController didMoveToParentViewController:self];
self.currentNotification = notificationViewController;
}];
then the view slides down perfectly, expect for that the text in the UIButton kind of fades in. It starts really small and animates to the correct font size.
How can I disable the animation of the text in the UIButton?
Is the effect you have something similar to what is below? I tried to imitate your situation by having a view with a UIButton inside with some some text set for the title of the button. I then animated the button similarly to the way you did. As you can see there isn't really a fade happening on the text of my button inside my view that is sliding so I wonder if there is something else at play for you. I have the code I used below also to mock the situation.
- (void)viewDidLoad {
[super viewDidLoad];
self.myView = [[UIView alloc] initWithFrame:CGRectMake(200, 0, 100, 100)];
self.myView.backgroundColor = [UIColor greenColor];
UIButton *myButton= [[UIButton alloc] initWithFrame:CGRectMake(10, 0, 80, 80)];
myButton.backgroundColor = [UIColor blueColor];
[myButton setTitle:#"fun times" forState:UIControlStateNormal];
[self.myView addSubview:myButton];
[self.view addSubview:self.myView];
UIButton *resetButton = [[UIButton alloc] initWithFrame:CGRectMake(300, 300, 50, 50)];
resetButton.backgroundColor = [UIColor blackColor];
[resetButton addTarget:self action:#selector(reset) forControlEvents:UIControlEventTouchUpInside];
UIButton *goButton = [[UIButton alloc] initWithFrame:CGRectMake(300, 100, 50, 50)];
goButton.backgroundColor = [UIColor redColor];
[goButton addTarget:self action:#selector(go) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:goButton];
[self.view addSubview:resetButton];
}
- (void)reset {
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
//Slide Up the notification
CGRect notificationsRect = self.myView.bounds;
notificationsRect.origin.y = 0;
notificationsRect.origin.x = 200;
self.myView.frame = notificationsRect;
} completion:nil];
}
- (void)go {
[UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
//Slide Down the notification
CGRect notificationsRect = self.myView.bounds;
notificationsRect.origin.y = 200;
notificationsRect.origin.x = 200;
self.myView.frame = notificationsRect;
} completion:nil];
}
Disable animations for UIButton using setAnimationsEnabled:(BOOL)enabled
Reference:https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIView_Class/index.html#//apple_ref/occ/clm/UIView/setAnimationsEnabled:
Related
I am trying to make a slide out notification bar for when the app receives a notification and the app is currently open and in the foreground. I got this working with a custom UIView (actually it's a UIButton) and an animation. For some reason though it won't register a press when I tap on it. It won't call the selector method. Code is below:
-(void)appOpenPush {
//get string
NSLog(#"got a push while app was open");
AppDelegate *appDelegate =(AppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *pushString = appDelegate.pushString;
//play sound
AudioServicesPlaySystemSound(MessageSound);
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
//note I am actually using a button here
UIButton *pushView =[[UIButton alloc] initWithFrame:CGRectMake(0, -75, [[UIScreen mainScreen] bounds].size.width,75)];
pushView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.8];
[pushView addTarget:self action:#selector(pushSlidePress) forControlEvents:UIControlEventTouchUpInside];
//set image
UIImageView *logo = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"icon120.png"]];
logo.frame=CGRectMake(5, 20, 35, 35);
logo.layer.cornerRadius=8;
logo.clipsToBounds=YES;
[pushView addSubview:logo];
UILabel *pushLabel = [[UILabel alloc] initWithFrame:CGRectMake(48, 34, 0, 0)];
pushLabel.text=pushString;
pushLabel.font=[UIFont systemFontOfSize:13];
[pushLabel sizeToFit];
pushLabel.textColor=[UIColor whiteColor];
[pushView addSubview:pushLabel];
//animate
UIWindow* currentWindow = [UIApplication sharedApplication].keyWindow;
[currentWindow addSubview:pushView];
[UIView animateWithDuration:0.4 delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
pushView.frame = CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width,75);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.4 delay:2.0 options:UIViewAnimationOptionCurveEaseIn animations:^{
pushView.frame = CGRectMake(0, -75, [[UIScreen mainScreen] bounds].size.width,75);
} completion:^(BOOL finished) {
[pushView removeFromSuperview];
}];
}];
}
Could anyone give me a pointer to why this isn't working? Is it because I am adding the UIButton to the main window? Any tips would be really helpful. thanks!
You have to add UIViewAnimationOptionAllowUserInteraction as an option to both of your animation blocks.
As per the documentation :
"Allow the user to interact with views while they are being animated."
Try this to avoid logo and pushLabel receive touches events:
logo.userInteractionEnabled = NO;
pushLabel.userInteractionEnabled = NO;
So it turns out you can't simply detect a press if the button is moving. I tested this by just adding the frame setup without it animating and it registered the press, when animation is turned on it doesn't. Seems that UIButton doesn't have tracking built in. I did come up with a quick fix. I just made a button the same size as the total animation area (i.e. the size of my slide out bar) and added that to the currentWindow on top of the animation frame. So it's just a clear invisible button on top of the animation but it's not moving itself. i.e:
UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0,[[UIScreen mainScreen]bounds].size.width , 75)];
[button addTarget:self action:#selector(pushSlidePress) forControlEvents:UIControlEventTouchUpInside];
[currentWindow addSubview:button];
[UIView animateWithDuration:0.4 delay:0.0 options:(UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionAllowUserInteraction) animations:^{
pushView.frame = CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width,75);
} completion:^(BOOL finished) {
[UIView animateWithDuration:0.4 delay:2.0 options:(UIViewAnimationOptionCurveEaseIn | UIViewAnimationOptionAllowUserInteraction) animations:^{
pushView.frame = CGRectMake(0, -75, [[UIScreen mainScreen] bounds].size.width,75);
} completion:^(BOOL finished) {
[pushView removeFromSuperview];
[button removeFromSuperview];
}];
}];
Obviously you are covering an area of the screen that might block other things being pressed, but it depends on your setup. The animation is quick and I only have one button that the notification bar will block and it's too quick to notice. Hopefully this will be helpful to someone else trying to achieve a similar thing. Thanks for your help guys.
In my app I'm trying to add a UITextField on a accessoryView. It should work as follow:
I press on a UITextField in the user interface of app
The keyboard pop up and cover my UITextField on the user interface
To edit text I wanted to show a UITextField in an accessoryView just above the keyboard
I looked on the web but I found only stuff to add button on an accessoryView, I hope you can help me to find a solution to add an UITextField on an accessoryView.
Thank you
UPDATE
This is what I mean:
I hope you understand better my question, I'm not looking for a solution that should user scroll view or something, I don't want to change the interface of my app...
in .h
UIView *customtoolbar;
in .m At viewdidload add thi code
customtoolbar=[[UIView alloc]initWithFrame:CGRectMake(0, self.view.frame.size.height+50, 320, 50)];`
after this add this methods
-(BOOL)textFieldShouldReturn:(UITextField *)textField{
[self pressdone];
return YES;
}
-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField{
//216 is keyboard default height in portrait(162 in landscape)
[UIView animateWithDuration:0.7 animations:^{
[self addtoolbar:CGRectMake(0, self.view.frame.size.height-216-50, 320, 50)];
}];
return YES;
}
-(UIView *)addtoolbar:(CGRect )frame{
customtoolbar.frame=frame;
customtoolbar.backgroundColor=[UIColor darkGrayColor];
//give new frame to your textfield
txtfld.frame=CGRectMake(5,10, 220, 30);
[customtoolbar addSubview:txtfld];
UIButton *done=[UIButton buttonWithType:UIButtonTypeCustom];
done.frame=CGRectMake(235,10, 60, 30);
[done setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
[done setTitle:#"Done" forState:UIControlStateNormal];
[done addTarget:self action:#selector(pressdone) forControlEvents:UIControlEventTouchUpInside];
[customtoolbar addSubview:done];
[self.view addSubview:customtoolbar];
return customtoolbar;
}
-(void)pressdone{
[self addtoolbar:CGRectMake(0, self.view.frame.size.height+50, 320, 50)];
//set there orignal frame of your textfield
txtfld.frame=CGRectMake(95, 170, 123, 37);
[self.view addSubview:txtfld];
[txtfld resignFirstResponder];
}
Add a view and then on top of it, please put a textfield and try. Below is the code.
UIView * container = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 40)];
[container setBackgroundColor:[UIColor redColor]];
UITextField * newTextfield = [[UITextField alloc] initWithFrame:CGRectMake(50, 0, 100, 44)];
[newTextfield setBackgroundColor:[UIColor yellowColor]];
[container addSubview:newTextfield];
self.textField.inputAccessoryView = container;
This contains some colors, just to distinguish and identify the views. Change and format according to your needs. It will work. :)
you can use scroll view for this in your app & set content offset
- (void)textFieldDidBeginEditing:(UITextField *)textField {
self.scroll.contentOffset = CGPointMake(0, textField.frame.origin.y);
}
i hope this is relevent to your problem
This is what i have done in my apps
Add observers to UIKeyboardWillHideNotification & UIKeyboardWillShowNotification
When u review notification resize your view keyboardFrame
double duration = [[notification userInfo][UIKeyboardAnimationDurationUserInfoKey] doubleValue];
int curve = [[notification userInfo][UIKeyboardAnimationCurveUserInfoKey] intValue];
NSValue *value = [notification userInfo][UIKeyboardFrameEndUserInfoKey];
CGRect rawFrame = [value CGRectValue];
CGRect keyboardFrame = [self.view convertRect:rawFrame fromView:nil];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:duration];
[UIView setAnimationCurve:curve];
// Resize your View
[UIView commitAnimations]
I want to create a turn-based match. When player received a notification player:receivedTurnEventForMatch:didBecomeActive:
I want to show a banner that slides from the top of the screen. "Your turn. Play" similar to the banner that Game Center shows when player is authenticated.
How can I do it? Should it be a UIViewController or UIAlert, or what?
here is a good example for notification for what you want, i hope that help you:
https://github.com/ekurutepe/MPNotificationView
or
https://github.com/edgurgel/CMNavBarNotificationView
or
https://github.com/terryworona/TWMessageBarManager
There are MANY ways to do what you mentioned. This is just one of them. Feel free to change the code around and read up on UIView animations to you can try out different things yourself.
-(void)myMethod {
// create UILabel and set its properties
UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 20, 320, 50)];
myLabel.backgroundColor = [UIColor grayColor];
NSString *myLabelText = #"Welcome back, Mike Lyman"; // showing you to use NSString for label text
myLabel.textAlignment = NSTextAlignmentCenter;
myLabel.text = myLabelText;
[self.view addSubview:myLabel]; // add UILabel to view
myLabel.frame = CGRectMake(0, -50, 320, 50); // set text label frame offscreen
// start the animation to slide UILabel into visible view
[UIView animateWithDuration:0.5 delay:0
options:UIViewAnimationOptionCurveLinear
animations:^ {
myLabel.frame = CGRectMake(0, 20, 320, 50);
}
completion:^(BOOL finished) {
// after 1 second delay, start sliding UILabel out of visible view
[UIView animateWithDuration:0.5 delay:1
options:UIViewAnimationOptionCurveLinear
animations:^ {
myLabel.frame = CGRectMake(0, -50, 320, 50);
}
completion:^(BOOL finished) {
NSLog(#"Done");
[self.view removeFromSuperview]; // remove UILabel from view completely
}];
}];
}
I have an object created from a class of type UIView to produce an unlimited number of views which then appear in smaller sizes in the middle of the screen. I used UITapGestureRecognizer to enlarge one of the views to fit the screen but the issue here is that the object is only usable within the first class and cannot be transferred to the second class which is the selector.
What are your suggestions regarding this particular issue?
How can I send my object to the selector to be able to use it there?
Thank you
Here is the first class which creates the object (derived from iCarousel) :
- (UIView *)carousel:(iCarousel *)carousel viewForItemAtIndex:(NSUInteger)index reusingView:(UIView *)view
{
UILabel *label = nil;
UIButton *close = [UIButton buttonWithType:UIButtonTypeRoundedRect];
//create new view if no view is available for recycling
if (view == nil)
{
view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320.0f, 460.0f)];
view.contentMode = UIViewContentModeCenter;
view.backgroundColor = [UIColor whiteColor];
label = [[UILabel alloc] initWithFrame:CGRectMake(100, -100, 100, 100)];
label.backgroundColor = [UIColor clearColor];
label.textAlignment = NSTextAlignmentCenter;
label.font = [label.font fontWithSize:50];
label.tag = 1;
[view addSubview:label];
close.frame = CGRectMake(0, 0, 30, 30);
[close setTitle:#"x" forState:UIControlStateNormal];
close.titleLabel.font = [UIFont systemFontOfSize:25];
[close addTarget:self action:#selector(closeMe:) forControlEvents:UIControlEventTouchUpInside];
[view addSubview:close];
UITapGestureRecognizer* tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapToMaximize:)];
tap.numberOfTapsRequired = 1;
[view addGestureRecognizer:tap];
}
else
{
//get a reference to the label in the recycled view
label = (UILabel *)[view viewWithTag:1];
}
label.text = [items[index] stringValue];
return view;
}
And the selector:
- (void)tapToMaximize:(UITapGestureRecognizer*)recognizer {
[UIView animateWithDuration:0.3
delay:0
options:UIViewAnimationOptionCurveLinear
animations:^{
carousel.transform = CGAffineTransformMakeScale(1, 1);
}
completion:^(BOOL finished) {
}];
}
So instead of using "carousel" which represents all the views, I want to use "view" so that I can only enlarge the current view and not all of them.
UITapGestureRecognizer inherits the view property from UIGestureRecognizer, which you can use to enlarge just that tap gesture recognizer's view:
- (void)tapToMaximize:(UITapGestureRecognizer*)recognizer {
UIView *viewToMaximize;
if ([recognizer.view isEqual:_maximizedView]) {
viewToMaximize = nil;
} else {
viewToMaximize = recognizer.view;
}
UIView *viewToUnmaximize = _maximizedView; // _maximizedView should be an instance variable on your view controller
[UIView animateWithDuration:0.3
delay:0
options:UIViewAnimationOptionCurveLinear
animations:^{
viewToMaximize.transform = CGAffineTransformMakeScale(1.1, 1.1);
viewToUnmaximize.transform = CGAffineTransformIdentity;
}
completion:^(BOOL finished) {
}];
_maximizedView = viewToMaximize;
}
Also, CGAffineTransformMakeScale(1, 1) will scale the view to its original size, so I bumped the scale up in my code snippet.
If I'm understanding this correctly you want to transform the UIView that you tapped on, which should be the carousel?
Assuming you added the tap gesture recognizer to self.view, then this is how you get the view you just tapped on:
- (void)tapToMaximize:(UITapGestureRecognizer*)recognizer
{
UIView *view = [self.view hitTest:[recognizer locationInView:self.view] withEvent:nil];
// you can now check to see if this view is the carousel
}
Once you know whether or not you tapped on the carousel, you can store it, pass it on to another class, transform it, or anything you like.
I have created a Table-view in main ViewController once i touch the row it will take to the next view controller(DetailViewController) where it display the image and name of dish.And once i tap the image it should get larger but it is not getting bigger .The below code is which i have tried in DetailViewController.
DetailViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
imageView=[[UIImageView alloc] initWithFrame:CGRectMake(10, 10,100, 100)];
CGRect textViewFrame = CGRectMake(10, 10, 300, 400);
textView = [[UITextView alloc] initWithFrame:textViewFrame];
textView.returnKeyType = UIReturnKeyDone;
textView.backgroundColor=[UIColor whiteColor];
textView.editable=NO;
textView.delegate = self;
[self.view addSubview:textView];
[textView addSubview:imageView];
textView.alpha = 0.9;
textView.font = [UIFont systemFontOfSize:15];
if(mrowno==0)
{
imageView.image=[UIImage imageNamed:#"Dosa.jpg"];
textView.text = #"\n\n\n\n\n\n\n\nDOSA\nDosa, ";
imageButton = [[UIButton alloc]init];
[imageButton setFrame:CGRectMake(0, 0, 100, 100)];
[imageButton addTarget:self action:#selector(imageTapped:) forControlEvents:UIControlEventTouchUpInside];
[imageView addSubview:imageButton];
}
Here is the method to make image larger
-(void)imageTapped:(UIButton*)in_sender
{
[UIView transitionWithView:in_sender.superview duration:0.8f options:UIViewAnimationOptionCurveLinear animations:^
{
[in_sender.superview setFrame:CGRectMake(0, 0, 300, 500)];
}
completion:^(BOOL finished)
{
}];
}
You can increase and decrease the size of image by pinch in and pinch out,If it required
-(void)viewDidLoad
{
UIPinchGestureRecognizer* pinch=[[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(pinching:)];
[self.imageView addGestureRecognizer:pinch];
}
-(void)pinching:(UIGestureRecognizer*) recognizer
{
UIPinchGestureRecognizer* pinch=(UIPinchGestureRecognizer*) recognizer;
self.imageView.transform=CGAffineTransformScale(self.imageView.transform, pinch.scale, pinch.scale);
pinch.scale=1;
NSLog(#"pinching");
}
You do not want to use transitionWithView. Instead, you want to use + animateWithDuration: delay:options:animations:completion: (or any of its shorter variants...)
[UIView animateWithDuration:0.3f delay:0.0f options:UIViewAnimationOptionCurveEaseInOut animations:^{
viewYouWantToAnimate.frame = CGRectMake(..., ..., ..., ...);
} completion:^{
//Add completion code here, or pass nil if you don't have anything to do.
}];
Edit: In case you were wondering what transitionWithView was used for... the AppleDocs have a great example of it adding animations for remove/addSubview methods (not frame modifications):
[UIView transitionWithView:containerView
duration:0.2
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{
[fromView removeFromSuperview];
[containerView addSubview:toView];
} completion:NULL];