I wrote this sample program to try and figure out what is going on. I have a textfield that upon clicking, shows a subview instead of showing a keyboard. In the subview, there is a dismiss button which shifts the subview so the top aligns with the bottom of the screen.
Just so I can build the subview in storyboard, the subview is aligned to the bottom edge of the screen and hidden
at startup. viewDidLoad
then calls the hideSubView
to shift it offscreen before it starts.
I have println
before and after each shift to tell me the position of the subview.
The problem I have is that the numbers don't add up. I specifically tell swift to offset the Y by 210, but somehow it only shifts it by 68.5 which is NOT the bottom of the screen (note this is not done by setting the subview as an inputview of the textfield). Yet when I click on the textfield, the subView animates from the bottom up, not some midway point. Can anyone explain why either of these two things is happening? One other thing is - where does the 457.0 for the initial minY come from? I checked the initial height of the subview which strangely is 143 (not 141.5).
Console Output (// - lines put in by me to clarify)
//hideSubview called from viewDidLoad
Before. minY:457.0 screenheight:667.0 offset:210.0
After. minY:525.5 screenheight:667.0 offset:210.0 //NOTE:457+210 is 667, not 525.5
//1st showSubView called by clicking on myTextField
Before. minY:525.5 screenheight:667.0 subview Height:141.5
After. minY:525.5 subView height:141.5
//hideSubView called by clicking on dismiss button
Before. minY:525.5 screenheight:667.0 offset:141.5
After. minY:667.0 screenheight:667.0 offset:141.5
//2nd showSubView called by clicking on myTextField
Before. minY:667.0 screenheight:667.0 subview Height:141.5
After. minY:525.5 subView height:141.5
//hideSubView called by clicking on dismiss button
Before. minY:525.5 screenheight:667.0 offset:141.5
After. minY:667.0 screenheight:667.0 offset:141.5
Main.storyboard
ViewController.swift
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var myTextField: UITextField!
@IBOutlet weak var mySubView: UIView!
var screenSize = UIScreen.mainScreen().bounds
var subViewIsVisible = false
override func viewDidLoad() {
super.viewDidLoad()
myTextField.delegate = self
hideSubView()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
@IBAction func dismissButtonClicked(sender: AnyObject) {
if subViewIsVisible {
hideSubView()
}
}
func textFieldDidBeginEditing(textField: UITextField) {
myTextField.endEditing(true)
if !subViewIsVisible {
showSubView()
}
}
func hideSubView () {
var offsetAmount = screenSize.height - mySubView.frame.minY
println("Before. minY:\(mySubView.frame.minY) screenheight:\(screenSize.height) offset:\(offsetAmount)")
UIView.animateWithDuration(0.25, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut , animations:
{
self.mySubView.frame.offset(dx: 0, dy: offsetAmount)
}, completion: {_ in
self.subViewIsVisible = false
self.mySubView.hidden = true
println("After. minY:\(self.mySubView.frame.minY) screenheight:\(self.screenSize.height) offset:\(offsetAmount)")
}
)
}
func showSubView () {
mySubView.hidden = false
println("Before. minY:\(mySubView.frame.minY) screenheight:\(screenSize.height) subview Height:\(mySubView.frame.height)")
UIView.animateWithDuration(0.25, delay: 0.0, options: UIViewAnimationOptions.CurveEaseOut , animations:
{
self.mySubView.frame.offset(dx: 0, dy: -self.mySubView.frame.height)
}, completion: {_ in
self.subViewIsVisible = true
println("After. minY:\(self.mySubView.frame.minY) subView height:\(self.mySubView.frame.height)")
}
)
}
}
Edit:
Constraints of mySubView: (easier to see than my comment for Bannings)