I'm making a login screen in iOS 8 using Storyboard (Xcode6 beta7). Here's an image of the basic idea:
Pressing inside any of the textfields brings up the keyboard, and pressing outside any of them dismisses it again using:
self.view.endEditing(true)
So pressing the login button makes the keyboard disappear.
When the user enters invalid login credentials I want the dialog view to increase in height and show some error message:
I'm doing this with an animation using the following function:
func increaseHeight(view: UIView, increment: CGFloat) {
UIView.animateWithDuration(1.0,
delay: 0.0,
usingSpringWithDamping: 0.3,
initialSpringVelocity: 3.0,
options: UIViewAnimationOptions.CurveEaseInOut,
animations: ({
view.frame = CGRect(
x: view.frame.origin.x,
y: view.frame.origin.y,
width: view.frame.width,
height: view.frame.height + increment
)
}),
completion: nil
)
}
If I invoke this function, let's say by pressing the login button, it's all working as I want. The animation is performed and the error message is shown.
To the the problem
However, if I first start to edit any of the textfields (i.e. bringing the keyboard up) and then press the login button, the animation is performed – but it bounces back to its original height.
How can I make the height increment persist after the keyboard has been dismissed?
If you are using auto-layout you need to change constraints not frame of the view.
heightOfViewConstraint.constant += increment
UIView animation....{
self.layoutIfNeeded()
}
This should keep your view stretched, but only if you are using auto-layout and constraints.
Related
I want to have my tableview increase in size and moves up when scrolled down while also keeping the constraint to the bottom layout. I thought I would try CGAffineTransform.
func MoveUP() {
// pop up login screen
let bottom = CGAffineTransform(translationX: 0, y: -30)
UIView.animate(withDuration: 0.7, delay: 0.2, options: [], animations: {
// Add the transformation in this block
// self.container is your view that you want to animate
self.numberOfProperties.transform = bottom
self.tableview.transform = bottom
}, completion: nil)
}
The problem with this is that it moves up the tableview but does not keep the proper constraints to the bottom. Many apps seems to have this behavior, what tool am I missing in order to achieve this result?
After making an animation on a UITextField, if I tap on my UITextField, it disappears. Why does this happen and how can I fix it? I'm not sure how to search for this online. Here's my animation code that I'm doing in viewDidAppear
UIView.animateWithDuration(1.0, delay: 0.0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.0, options: [], animations: {
self.userName.center.x += self.view.bounds.width
self.userName.alpha = 1.0
}, completion: nil)
Before this I set the UITextField to be off the screen. So what my animation is supposed to do is start from outside of the screen and animate it to be visibly in the center of the screen. Don't know if that makes a difference in this question though.
The animation works great, it's just that when I try to tap on the UITextField to enter a username, the entire UITextField just disappears and I'm left with just a keyboard. I'm sure it's something simple I'm missing. Can someone lead me in the right direction?
I am making a Karaoke app that a user needs to be able to start-over by pressing a button.
I have a UIScrollView that contains a large block of text in a UITextView.
I am using UIView.animateWithDuration to scroll the text for a certain duration. I need to be able to interrupt/stop the animation and reset it back to the beginning.
Unfortunately, for me, whenever I stop the animation, the UITextView disappears and I can't seem to re-add it.
let bottomOffset:CGPoint = CGPoint(x: 0, y: self.textView.frame.size.height)
UIView.animateWithDuration(NSTimeInterval(duration),
delay: NSTimeInterval(0.0) ,
options: UIViewAnimationOptions.CurveLinear,
animations: {
self.scrollView.setContentOffset(bottomOffset, animated: false)
},
completion: { finished in
reset()
}
)
I am stopping the animation by calling:
UIView.animateWithDuration(0.0, animations: {
self.scrollView.scrollRectToVisible(CGRect(x: 0, y: 0, width: 0, height: 0), animated: true)
})
I need to figure out how to:
Stop the animation
Keep the UITextView visible
Scroll the UIScrollView back to the top
Start scrolling again
My codebase is in Swift, but I will gladly accept answers in Objective-C.
I have the most strange situation with a custom keyboard. First of all, I have set up a dummy view for the textfield, in order to hide the stock keyboard let dummyView : UIView = UIView(frame: CGRect(x: 0, y: 0, width: 1, height: 1))
amountField.inputView = dummyView
Then I have my custom keyboard which animates when editing begins in the text field
func textFieldDidBeginEditing(textField: UITextField) {
keyboardContainer.hidden = false
UIView.animateWithDuration(0.6, animations: {
self.keyboardContainer.frame = self.keyboardScreenPosition!
}, completion: {
finished in
if finished {
//just in case
}
})
}
Also, I have set up a button which should end editing and hide my custom keyboard
#IBAction func calculeaza(sender: AnyObject) {
self.amountField.resignFirstResponder()
UIView.animateWithDuration(0.6, animations: {
self.keyboardContainer.frame.origin.y = self.view.bounds.height
}, completion: {
finished in
if finished {
}
})
}
The most strange part comes with the resignFirstResponder(). Let me explain: If that part is not included, the keyboard hides just fine (but the text field keeps on blinking cursor which is not an option ofc). If the resigning part is included, the keyboard animates from the top to its current position, then on pressing the button again it does slides down as intended. I am really puzzled on why is this happening...I debugged the sizes of the view and the heights are ok so it should slide down from the beginning. I really dont understand what is happening. Any help is much appreciated, many thanks!
EDIT: another strange effect is if I move the resign part (or the super end editing) in the animation ending closure. The keyboard slides just fine, then it reappears on screen
This sounds like an issue with autolayout constraints. Those are updated after the animateWithDuration which is potentially causing this odd behavior. If you have (a) constraint(s) in the Storyboard used for autolayout, try updating that(/those). If you haven't already, you'll need to add it as an IBOutlet and animate the autolayout change in the duration.
For example, say the constraint is called theRelevantConstraint. Then replace the middle lines
self.theRelevantConstraint.constant = valueItShouldBe
UIView.animateWithDuration(0.6, animations: {
self.view.layoutIfNeeded()
}, completion: {
finished in
if finished {
}
})
I am attempting to animate a tab bar to move from below the bottom of the screen to the top while simultaneously adjusting a view's height to shrink by the height of the tab bar. Essentially, I have a "hidden" tab bar that when it unhides should animate into view and the displayView should adjust for the space the tab bar now takes up.
However, the animation is jumpy for the display view. It seems that the display view animates fine, but the subviews automatically adjust their height without any animation. Any direction on fixing this would be appreciated.
I will accept aid in either objective-c or swift, as the translation is fairly easy.
//Displays tab bar with slide up animation. If animated is false, all other params are unused
func displayTabBar(animated:Bool, duration:NSTimeInterval = 0.5, delay:NSTimeInterval = 0, options:UIViewAnimationOptions = UIViewAnimationOptions.CurveLinear, completion:((Bool) -> Void)? = nil){
if(animated){
UIView.animateWithDuration(duration, delay: delay, options: options, animations: {
self.adjustTabBarDisplayed()
}, completion: completion)
UIView.animateWithDuration(duration, delay: delay, options: options, animations: {
self.adjustDisplayViewTabDisplayed()
}, completion: nil)
}
else{
self.adjustTabBarDisplayed()
self.adjustDisplayViewTabDisplayed()
}
}
//Adjusts frame of tab bar to display tab bar
private func adjustTabBarDisplayed(){
self.tabBar.frame = CGRectMake(0,UIScreen.mainScreen().bounds.height - self.tabBar.bounds.height, self.tabBar.bounds.width, self.tabBar.bounds.height)
}
//Adjusts frame of display view to match displayed tab bar
private func adjustDisplayViewTabDisplayed(){
self.displayView.frame = CGRectMake(0,0,self.displayView.bounds.width, UIScreen.mainScreen().bounds.height - self.tabBar.bounds.height)
}
When you modify a view's size, it doesn't lay out its subviews immediately. Instead, it sets a flag indicating that it needs layout. Later, after the system has finished dispatching the event that ended up calling displayTabBar, it runs the display refresh code. The display refresh code finds views that have the needs-layout flag set and tells them to lay themselves out (by sending them layoutSubviews).
Here, you are changing your display view's size inside an animation block. Therefore change to your display view's frame will be animated. But the frames of its subviews are changing outside the animation block; they're changing later during the layout phase. You need to make them change inside the animation block.
Lucky for you, that's easy. Just call self.displayView.layoutIfNeeded() inside the animation block. Also, you only need one animation block, since all of the animation parameters are identical:
func displayTabBar(animated:Bool, duration:NSTimeInterval = 0.5, delay:NSTimeInterval = 0, options:UIViewAnimationOptions = UIViewAnimationOptions.CurveLinear, completion:((Bool) -> Void)? = nil){
if(animated){
UIView.animateWithDuration(duration, delay: delay, options: options, animations: {
self.adjustTabBarDisplayed()
self.adjustDisplayViewTabDisplayed()
// ADD THIS LINE
self.displayView.layoutIfNeeded()
}, completion: completion)
}
else{
self.adjustTabBarDisplayed()
self.adjustDisplayViewTabDisplayed()
}
}
Use the below line of code in animation block
scrollView.layoutIfNeeded()