I have a readonly UITextView, and I'm updating the text.
When the new text appears, I want it to animate as follows: New text slides in from the right, as the old text slides offscreen toward the left side.
Is it possible to do this with transitionWithView? If not, what's the best way to do it? I can make it do a CrossDissolve, but that's not the animation I'm looking for:
[UIView transitionWithView:self.storyTextView
duration:0.5
options:UIViewAnimationOptionTransitionCrossDissolve
animations:^{
[self.storyTextView setText:withStory.storyText];
}
completion:nil];
The reason for insisting on the right to left animation is because eventually I want the user to be able to trigger it by swiping toward the left on the UITextView.
CATransition will allow you to do this, with a transition type of 'push' and a subtype of 'from right'. It's very straightforward to use:
CATransition *transition = [CATransition new];
transition.type = kCATransitionPush;
transition.subtype = kCATransitionFromRight;
// Make any view changes
self.textView.text = newText;
// Add the transition
[self.textView.layer addAnimation:transition forKey:#"transition"];
Note that this, while it's what you've asked for, won't fit nicely with a gesture without some extra tinkering - to tie it to a gesture you'd need to do something like set the layer speed to 0 and the manually update the progress of the animation to match your gesture.
What about just using UIView animateWithDuration and slide the one textView to the right while sliding a new textView from the left. Here is an example just have to work out the positions. Let me know if this is what you were looking to do.
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
self.textView2.frame = CGRectMake(1000.0,self.textView1.frame.origin.y,self.textView2.frame.size.width,self.textView2.frame.size.height);
}
- (IBAction)animate:(id)sender {
[UIView animateWithDuration:0.5 animations:^{
self.textView1.frame = CGRectMake(-200.0,self.textView1.frame.origin.y,self.textView1.frame.size.width,self.textView1.frame.size.height);
[UIView animateWithDuration:0.5 animations:^{
self.textView2.center = (CGPointMake(200, 200));
}];
}];
}
You can also try something like this.
You can create a containerView for your text view and then change the coordinates using UIView animations to give it a slide from right to left.
Please see code below.
First declare a container view and the make the required text view its subview.
In .h
#property (strong, nonatomic)IBOutlet UIView *containerView;
#property (strong, nonatomic)IBOutlet UITextView *childTextView; //I have set it as subview in xib
In .m make sure to set the following in viewDidLoad or in Xib
self.containerView.clipsToBounds = YES;
Gestures
UISwipeGestureRecognizer *recog = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:#selector(changeText)];
recog.direction = UISwipeGestureRecognizerDirectionLeft;
[self.containerView addGestureRecognizer:recog];
Beautification (for this you would need QuartzCore/QuartzCore.h)
self.containerView.layer.borderWidth = 1.0f;
self.containerView.layer.borderColor = [UIColor lightGrayColor].CGColor;
self.containerView.layer.cornerRadius = 5.0f;
To the Point
- (void)changeText
{
[UIView animateWithDuration:0.3f animations:^(void){
CGRect endPos = self.childTextView.frame;
endPos.origin.x -= endPos.size.width; //Move it out of the view's frame to the left
self.childTextView.frame = endPos;
} completion:^(BOOL done){
CGRect startPos = self.childTextView.frame;
startPos.origin.x += (2*startPos.size.width);// this will take it to the right.
self.childTextView.frame = startPos;
self.childTextView.text = #"Changed text";
[UIView animateWithDuration:0.2f animations:^(void){
CGRect displayPos = self.childTextView.frame;
displayPos.origin.x -= displayPos.size.width; // To compensate for the double +ve on top
self.childTextView.frame = displayPos;
}];
}];
}
Related
I am trying to apply mask to backend view but am unable reach my expectation. I want the view should be like showing in the below image.
I tried to implement in my own way but the mask view also comes up from bottom. When we click on iCloud option in iPad immediately the backend view becomes in gray color and the custom view comes up from bottom. I want same feature needs to be implemented in my application. Please help me. Thanks in advance.
I strongly suggest you use this nice and tidy git code
https://github.com/jmascia/KLCPopup
KLCPopup really does a very nice job in implementing modal views with animations, blur, fade, etc.
Very easy to set up and use, it's litreally just
" choose your view "
" choose where you want it "
" Add effects if you want some "
"there you go "
have fun ;)
Follow below steps to achieve your requirements-
1) Create a BaseView & Add a CustomView on the center of the BaseView.
2) Set the background color of BaseView as black with 50% opacity.
3) Keep the actual transform of the CustomView in a variable as
CGAffineTransform m_actualTransformOfCustomView =
m_customView.transform;
4) Scale the CustomView to a small 0.01 , 0.01 using
self.m_customView.transform = CGAffineTransformScale(m_actualTransformOfCustomView, 0.01, 0.01);
4) Use [UIView amimateWithDuration:] api to change the transform of the custom view to original as-
[UIView animateWithDuration:0.5f
delay:0
options:UIViewAnimationOptionCurveEaseOut
animations:^
{
self.m_customView.transform = CGAffineTransformScale(m_actualTransformOfCustomView, 1.0, 1.0);
}
completion:^(BOOL finished)
{
}
];
}
My own way is working now properly. Here is the code snippet. Enjoy!
-(IBAction)show:(id)sender{
customView = [[UIView alloc] initWithFrame:self.view.frame]; // Mask View
customView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.3f];
[self.view addSubview:customView];
// customConfigurationView // PopUp view
CGRect frameCustmVw = customConfigurationView.frame;
frameCustmVw.origin.y = self.view.frame.size.height;
frameCustmVw.origin.x = 134;
customConfigurationView.frame = frameCustmVw;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
frameCustmVw.origin.y = 200;
customConfigurationView.frame = frameCustmVw;
[self.view addSubview:customConfigurationView];
[UIView commitAnimations];
[txtClientID becomeFirstResponder];
}
-(IBAction)remove:(id)sender{
[customView removeFromSuperview]; // Remove mask view
CGRect CustmFrame = customConfigurationView.frame;
CustmFrame.origin.y = 200;//self.view.frame.size.height - customConfigurationView.frame.size.height;
customConfigurationView.frame = CustmFrame;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
CustmFrame.origin.y = self.view.frame.size.height;
customConfigurationView.frame = CustmFrame;
[UIView commitAnimations];
}
oky , my answer regarding the way how settings app doing this, it is simple ... they are just presenting a navigation controller thats all, for example
just create a view controller subclass for example (i named it as TestViewController) and set it size to freeform in attribute inspector and change its frame's width and height to your required values and add view components
it will show the view controller with width and height of 540*620 with your animation
that's all
- (IBAction)presentAction:(id)sender
{
TestViewController *testVc = [[TestViewController alloc]initWithNibName:#"TestViewController" bundle:nil];
UINavigationController *aNavController = [[UINavigationController alloc] initWithRootViewController:testVc];
aNavController.modalPresentationStyle = UIModalPresentationFormSheet;
aNavController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentViewController:aNavController animated:YES completion:nil];
}
So i have a really weird problem at my hands and hours of search has provided nothing.
I have a uiview containing a uitextfield. Now initially this view is outside of the visible screen with coordinates like x=-500,y=-500.
However in response to a button press this view animates and moves into the center of the screen.
Now whenever i tap on a uitextfield that is the subview of this view.This view moves back to its original coordinates outside the screen.
I have frantically checked my code and there is nothing that is moving the view outside again once its in. Any help in explaining this very unfamiliar behaviour would be really appreciated.
This code moves the view onto the screen
- (IBAction)Register:(id)sender {
//(self.view.frame.size.width/2)-(self.SignUp_Screen.frame.size.width/2);
//self.login_Screen.hidden = YES;
self.blurView.hidden = NO;
//self.SignUp_Screen.layer.zPosition = 5;
NSLog(#"Register");
self.SignUp_Screen.hidden = NO;
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
self.SignUp_Screen.frame = CGRectMake(35, 50,self.SignUp_Screen.frame.size.width , self.SignUp_Screen.frame.size.height);
} completion:^(BOOL finished) {
}];
}
and these are the delegate methods for the textfield
-(void)textFieldDidEndEditing:(UITextField *)textField
{
NSLog(#"TextFieldEndEditing");
[textField resignFirstResponder];
}
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
NSLog(#"textFieldShouldReturn");
[textField resignFirstResponder];
return YES;
}
As Wezly hints at, if you are using autolayout, you don't modify the frame directly anymore. That's the old world. You want to have an Outlet / property for the constraint and animate it.
[UIView animateWithDuration:0.25
animations:^{
SignUp_Screen.centerXConstraint.constant = ...;
SignUp_Screen.centerYConstraint.constant = ...;
[SignUp_Screen layoutIfNeeded];
}];
See here and here for more details.
You should not modify frame if you are using auto layout. You should animate view by animating constraint's constant. For example:
NSLayoutConstraint *viewY; //constraint from superview top to view top
viewY.constant = 100;
[self.view setNeedsUpdateConstraints];
[UIView animateWithDuration:0.3f animations:^{
[self.view layoutIfNeeded];
}];
The way i solved this problem was by linking an IBOutlet to the constraint I wanted to change and then animating it's constant value.
.h
#interface ViewController : UIViewController {
IBOutlet NSLayoutConstraint *constraintHandle;
}
.m
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
constraintHandle.constant = self.view.center.x;
[SignUp_Screen layoutIfNeeded];
} completion:^(BOOL finished) {
}];
Don't forget to link the IBOutlet to your constraint in your storyboard or xib.
I am trying to give the flip effect to a UIview as if on one side I had some content and on the other side I had some other in the following way:
[UIView transitionWithView:FlipView duration:0.7
options:UIViewAnimationOptionTransitionFlipFromRight animations:^{
//imageView.image = secondImage;
FlipImage.hidden = YES;
for (UIButton *btn in arrayoflabels) {
btn.hidden = YES;
}
containerViewSplashit.hidden = NO;
containerViewSplashit.alpha = 1.0;
closeButton.hidden = NO;
} completion:nil];
The only problem is that it flips and then when it finishes flipping, it shows the hidden content I want to show, but it doesn't give that front to back effect that it swops side when it passes the middle. how can i fix this?
You should try to ad the UIViewAnimationOptionAllowAnimatedContent option to the animation option because you have animatable changes in your block (hidden, alpha).
I have a UIScrollView at the very top (just below the navigation bar) of a UITableViewController using Storyboards. The UIScrollView's default size is 320x50. When the user holds the scrollView for at least 1 second, I want the UIScrollView to get twice as big (320x100) in order to show additional details with an animation. The UITableView right below it should animate with it if possible and move down 50.
Holding the UIScrollView for at least 1 second when it's in the bigger setting will result in the opposite animation, and the UIScrollView will animate back to its original size.
How would I do this? Thank you ahead of time! Here's what I have so far:
- (void)viewDidLoad {
[super viewDidLoad];
self.featureScrollExpanded = NO;
UILongPressGestureRecognizer* featureHold = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector (longHold:)];
[featureHold setDelaysTouchesBegan : YES];
featureHold.minimumPressDuration = 0.6;
featureHold.numberOfTouchesRequired = 1;
[self.featureScrollView addGestureRecognizer:featureHold];
[featureHold release];
}
- (void)longHold:(UIGestureRecognizer*)sender {
if (self.featureScrollExpanded==NO) {
self.featureScrollExpanded=YES;
//make it bigger
}
else {
self.featureScrollExpanded=NO;
//make it smaller
}
}
Do an animation:
CGRect frame = yourScrollView.frame;
frame.size.height += 50;
[UIView animateWithDuration:0.6
animations:^{
yourScrollView.frame = frame;
} completion:^(BOOL finished) {
//do your other animation here if you want to
//or do them both together and lose this block
}
];
Or if you want it a bit more with an overview:
CGRect frame = yourScrollView.frame;
frame.size.height += 50;
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.6];
[self.yourScrollView setFrame:frame];
[UIView commitAnimations];
I wrote a custom UITableViewCell - image view, button and three labels now I am trying to add some animations to it. So once I tap the button, it fades away and the spinner replaces the button. After two seconds the cell is overlaid with a red color, as a subview of cell fades in, then the indicator is removed and and red overlay starts fading back out. As well the button I previously removed fades back in.
(I could not phrase it a better way :P )
The method is :
-(void)rentButtonPressed:(id)sender
{
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
[indicator startAnimating];
indicator.center = self.rentButton.center;
[UIView animateWithDuration:0.2
animations:^{self.rentButton.alpha = 0.0;}
completion:^(BOOL finished){
[self.rentButton removeFromSuperview];
[self addSubview:indicator];
}
];
UIView *overlay = [[UIView alloc] initWithFrame:self.backgroundImage.frame];
overlay.alpha = 0.0;
overlay.backgroundColor = [UIColor redColor];
[self.contentView addSubview:overlay];
[UIView animateWithDuration:0.4
delay:2.0
options:UIViewAnimationCurveEaseInOut
animations:^{
[indicator removeFromSuperview];
overlay.alpha = 0.4;
}
completion:^(BOOL finished){
[UIView animateWithDuration:0.4
animations:^{ overlay.alpha = 0.0; }
completion:^(BOOL finished)
{
[overlay removeFromSuperview];
}
];
[self.contentView addSubview:self.rentButton];
[UIView animateWithDuration:0.4 animations:^{ self.rentButton.alpha = 1.0;}];
[self.delegate didTryToRentMovieAtCell:self];
}
];
}
So the code does fade out the button, replace it with spinner and fades in the red overlay. The problem is, the red overlay does not fade away, but disappears same with the button, instead of fading in, it just appears.
During your animation, you are changing the view hierarchy by adding and removing subviews. The UIView class method animateWithDuration:animations:completion is intended only animating property changes in a view, and not for changing the view hierarchy.
Try using the UIView class method transitionWithView:duration:options:animations:completion: instead, and use the cell's content view as the "container."
This documentation is helpful in distinguishing between animating view property changes and animating view transitions, specifically the section "Changing the Subviews of a View":
http://developer.apple.com/library/ios/#documentation/windowsviews/conceptual/viewpg_iphoneos/animatingviews/animatingviews.html