Update April 21, 2016: Swift 2.2 with Xcode 7.3.
Here is an issue that new iOS developers may often ignore:
The default height of the iPhone status bar at the top of the screen is 20
When the personal hotspot WiFi function is turned on, the height of the status bar is increased to 40
To test the double-height condition, the simplest method is to use the iOS simulator. Select Hardware -> Toggle In-Call Status Bar to change the status bar height.
Let's try this simple code:
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.orangeColor()
let labelHeight : CGFloat = 30
let labelWidth : CGFloat = 150
let statusHeight : CGFloat = UIApplication.sharedApplication().statusBarFrame.size.height
let labelTop = UILabel(frame: CGRectMake(0,statusHeight,labelWidth,labelHeight))
labelTop.backgroundColor = UIColor.blueColor()
labelTop.textColor = UIColor.whiteColor()
labelTop.text = "Top"
labelTop.textAlignment = NSTextAlignment.Center
view.addSubview(labelTop)
let labelBottom = UILabel(frame: CGRectMake(0,view.bounds.height-labelHeight,labelWidth,labelHeight))
labelBottom.backgroundColor = UIColor.blueColor()
labelBottom.textColor = UIColor.whiteColor()
labelBottom.text = "Bottom"
labelBottom.textAlignment = NSTextAlignment.Center
view.addSubview(labelBottom)
}
Run the iOS simulator, and the result is:
When the status bar is increased in height, the screen becomes:
Both the top and bottom labels with blue background color are moved downwards by 20
To fix this issue, modify the code as:
let statusHeightDefault : CGFloat = 20
var statusHeight : CGFloat!
var labelBottom : UILabel!
let screenHeight : CGFloat = UIScreen.mainScreen().bounds.height
let labelHeight : CGFloat = 30
let labelWidth : CGFloat = 150
var labelBottomY : CGFloat!
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(statusBarHeightChanged), name: UIApplicationWillChangeStatusBarFrameNotification, object: nil)
view.backgroundColor = UIColor.orangeColor()
statusHeight = UIApplication.sharedApplication().statusBarFrame.size.height
let labelTop = UILabel(frame: CGRectMake(0,statusHeightDefault,labelWidth,labelHeight))
labelTop.backgroundColor = UIColor.blueColor()
labelTop.textColor = UIColor.whiteColor()
labelTop.text = "Top"
labelTop.textAlignment = NSTextAlignment.Center
view.addSubview(labelTop)
labelBottomY = screenHeight - statusHeight + statusHeightDefault - labelHeight
labelBottom = UILabel(frame: CGRectMake(0,labelBottomY,labelWidth,labelHeight))
labelBottom.backgroundColor = UIColor.blueColor()
labelBottom.textColor = UIColor.whiteColor()
labelBottom.text = "Bottom"
labelBottom.textAlignment = NSTextAlignment.Center
view.addSubview(labelBottom)
}
func statusBarHeightChanged() {
statusHeight = UIApplication.sharedApplication().statusBarFrame.size.height
labelBottomY = screenHeight - statusHeight + statusHeightDefault - labelHeight
UIView.animateWithDuration(0.3, animations: {
self.labelBottom.frame = CGRectMake(0,self.labelBottomY,self.labelWidth,self.labelHeight)
})
}
The video for this solution shows the bottom label position is now dynamically adjusted according to different the status bar heights:
Refererence:
personal hotspot 造成 status bar 高度改變
Screen size data of iPhones 4s, 5/5s/5c, 6/6s, and 6 Plus/6s Plus
Instead of notification, u could use viewWillLayoutSubviews, viewDidLayoutSubviews
ReplyDeleteFor me, these two methods are not called when the status bar is changed, but the following two methods in AppDelegate work fine:
Deleteapplication: willChangeStatusBarFrame
application: didChangeStatusBarFrame
Thanks for sharing this post. Your post is really helpful.
ReplyDelete