iOS: UIWindow in iOS
2015-06-08 15:41
363 查看
原文链接:http://www.fantageek.com/1317/uiwindow-in-ios/
一篇中文翻译:点击打开链接
In this article, I ‘ll share what I know about UIWindow
An app can have many UIWindow. The key window is the one that is designated to receive keyboard and other non-touch related events. Only one window at a time may be the key window.
You call makeKeyAndVisible or makeKeyWindow to make a UIWindow become the keyWindow. Note that UIWindow is hidden by default, so makeKeyAndVisible both makes a UIWindow become keyWindow and set its hidden property to NO
Simply add the following code in application:didFinishLaunchingWithOptions:
then rotate the device/simulator, you will see that the green color view is always at position {0, 0},
The UIWindow’s coordinate system is always in portrait orientation. It applies the rotation by setting its rootViewController’s view’s transform. So starting in iOS 4, application is advised to have rootViewController. See this wonderful answer from rob After
rotation UIView coordinates are swapped but UIWindow’s are not?
Note that UIApplication has an instance method “windows”
The app’s visible and hidden windows. (read-only)
This property contains the UIWindow objects currently associated with the app. This list does not include windows created and managed by the system, such as the window used to display the status bar.
You can get the keyboard window by traversing this windows array. Code extracted from SVProgressHUD. Note that when the keyboard is shown, the windows array contains another window of type UITextEffectsWindow, that is the keyboard
As said previously, The UIWindow’s coordinate system is always in portrait orientation. Keyboard is a window, so its frame is always (0 0; 320 480) regardless of device orientation. When you rotate the device, the system applies a rotation transform to the
keyboard window
User rotates the device to portrait
User rotates the device to landscape
Notification
If you register for UIKeyboardWillShowNotification, you can confirm this
User rotates the device to portrait
UIKeyboardFrameEndUserInfoKey = “NSRect: {{0, 264}, {320, 216}}”;
User rotates the device to landscape
UIKeyboardFrameEndUserInfoKey = “NSRect: {{0, 0}, {162, 480}}”;
So in your UIKeyboardWillShowNotification handler, you should convert it to your view coordinate system. Code extracted from Keyboard “WillShow” and “WillHide” vs. Rotation
As said previously, the windows array does not contain the statusbar window. Statusbar window is of type UIStatusBarWindow, you can get it with the following code (extracted from FLEX)
Like the keyboard window, the status bar frame is unchanged. When you rotate the device, the system applies rotation transform to the status bar
User rotates the device to portrait
User rotates the device to landscape
statusBarFrame
UIApplication has a property called statusBarFrame, which is always reported in portrait coordinate system.
User rotates the device to portrait
statusBarFrame {{0, 0}, {320, 20}}
User rotates the device to landscape
statusBarFrame {{300, 0}, {20, 480}}
If you merely want to get the status height, regardless of orientation, you can just get the max
Notification
When the device is rotated, the system issues UIApplicationWillChangeStatusBarFrameNotification and UIApplicationDidChangeStatusBarFrameNotification.
Let’s now handle UIApplicationDidChangeStatusBarFrameNotification to see
I don’t know why but the WillChange notification gives me the final result, while the DidChange notification give me the old result. By result, I mean the value of the statusBarFrame
I also see that no libraries use the DidChange notification
To create an alertview, you can simply present an UIViewController (with smaller size). For advanced cases, you must understand the presentation context. And the way to use your alertview is a bit hard. What we always want is a simple call
It ‘s not to say that some view can appears on top of your alert view, so they defeats your purpose as an alertview
The fancy way is to work with UIWindow. I see many libraries use one of these 2 approaches
Some libraries like OLGhostAlertView, SVProgressHUD, WYPopoverController, MTStatusBarOverlay … don’t use rootViewController. They can create new UIWindow (MTStatusBarOverlay) or use existing UIWindow, they addSubview directly to the window, so they handle orientation
by listen to UIApplicationDidChangeStatusBarOrientationNotification or UIApplicationWillChangeStatusBarFrameNotification
The handler is like this, extracted from SVProgressHUD. The idea is manually get the orientation and applies a rotation transform to their view
How to add view to existing window
Libraries have their own strategy to add view to existing window
SVProgressHUD tries to add to the front window
How the OS creates AlertView
Watch WWDC 2014 Session 228 A Look Inside Presentation Controllers, they said
Behind the scenes, the framework creates a window on your app’s behalf, but this predates iOS 8 window rotation behavior, so this window is technically still in portrait.
We then add the action sheet to that window and mimic the transform hierarchy of the presenting view to get into the right orientation.
Some libraries, like FLEX, SIAlertView, … create new UIWindow and assign rootViewController to that window. This way orientation is reported to the rootViewController. They then simply add view to the rootViewController.view and handle orientation right in
the view controller.
Code extracted from FLEXViewExplorerViewController
Since FLEX creates new Window, it must consults the app original Window for rotation capability. Note the infoPlistSupportedInterfaceOrientationsMask and viewControllerForStatusBarAndOrientationProperties, you can learn much from it
Since UIWindow is a UIView subclass, you can do many things you already know with UIView. For example, FLEX override pointInside:withEvent: to intercept touch through its toolbar
In iOS 8, Apple introduce Size Classes, and “Rotation is an animated bounds change”. And UIWindow is reported in device orientation
WWDC 2014 Session 216 Building Adaptive Apps with UIKit
Trait Environments are a new protocol that are able to return their current Trait Collection, and these include Screens, Windows, View Controllers, and also Views.
All of these are able to return their current Trait Collection to you to use to determine how your interface should be laid out.
See Is [UIScreen mainScreen].bounds.size becoming orientation-dependent in iOS8?
UIScreen is now interface oriented:
[UIScreen bounds] now interface-oriented
[UIScreen applicationFrame] now interface-oriented
Status bar frame notifications are interface-oriented
Keyboard frame notifications are interface-oriented
Multiple UIWindows
To create a new UIWindow over the main window
Advantages, problems, examples of adding another UIWindow to an iOS app?
The difference between a UIWindow and a UIView
Using multiple UIWindows in iOS applications
Technical Q&A QA1688 Why won’t my UIViewController rotate with the device?
After rotation UIView coordinates are swapped but UIWindow’s are not?
WWDC 2014 Session 214 View Controller Advancement in iOS 8
一篇中文翻译:点击打开链接
In this article, I ‘ll share what I know about UIWindow
keyWindow
An app can have many UIWindow. The key window is the one that is designated to receive keyboard and other non-touch related events. Only one window at a time may be the key window.You call makeKeyAndVisible or makeKeyWindow to make a UIWindow become the keyWindow. Note that UIWindow is hidden by default, so makeKeyAndVisible both makes a UIWindow become keyWindow and set its hidden property to NO
UIWindow is always portrait
Simply add the following code in application:didFinishLaunchingWithOptions:The UIWindow’s coordinate system is always in portrait orientation. It applies the rotation by setting its rootViewController’s view’s transform. So starting in iOS 4, application is advised to have rootViewController. See this wonderful answer from rob After
rotation UIView coordinates are swapped but UIWindow’s are not?
Keyboard is a window
Note that UIApplication has an instance method “windows”The app’s visible and hidden windows. (read-only)
This property contains the UIWindow objects currently associated with the app. This list does not include windows created and managed by the system, such as the window used to display the status bar.
You can get the keyboard window by traversing this windows array. Code extracted from SVProgressHUD. Note that when the keyboard is shown, the windows array contains another window of type UITextEffectsWindow, that is the keyboard
keyboard window
User rotates the device to portrait
Notification
If you register for UIKeyboardWillShowNotification, you can confirm this
UIKeyboardFrameEndUserInfoKey = “NSRect: {{0, 264}, {320, 216}}”;
User rotates the device to landscape
UIKeyboardFrameEndUserInfoKey = “NSRect: {{0, 0}, {162, 480}}”;
So in your UIKeyboardWillShowNotification handler, you should convert it to your view coordinate system. Code extracted from Keyboard “WillShow” and “WillHide” vs. Rotation
Statusbar is a window
As said previously, the windows array does not contain the statusbar window. Statusbar window is of type UIStatusBarWindow, you can get it with the following code (extracted from FLEX)User rotates the device to portrait
statusBarFrame
UIApplication has a property called statusBarFrame, which is always reported in portrait coordinate system.
statusBarFrame {{0, 0}, {320, 20}}
User rotates the device to landscape
statusBarFrame {{300, 0}, {20, 480}}
If you merely want to get the status height, regardless of orientation, you can just get the max
Notification
When the device is rotated, the system issues UIApplicationWillChangeStatusBarFrameNotification and UIApplicationDidChangeStatusBarFrameNotification.
Let’s now handle UIApplicationDidChangeStatusBarFrameNotification to see
I also see that no libraries use the DidChange notification
How to create alert view
To create an alertview, you can simply present an UIViewController (with smaller size). For advanced cases, you must understand the presentation context. And the way to use your alertview is a bit hard. What we always want is a simple callThe fancy way is to work with UIWindow. I see many libraries use one of these 2 approaches
Don’t use rootViewController approach
Some libraries like OLGhostAlertView, SVProgressHUD, WYPopoverController, MTStatusBarOverlay … don’t use rootViewController. They can create new UIWindow (MTStatusBarOverlay) or use existing UIWindow, they addSubview directly to the window, so they handle orientationby listen to UIApplicationDidChangeStatusBarOrientationNotification or UIApplicationWillChangeStatusBarFrameNotification
The handler is like this, extracted from SVProgressHUD. The idea is manually get the orientation and applies a rotation transform to their view
How to add view to existing window
Libraries have their own strategy to add view to existing window
SVProgressHUD tries to add to the front window
How the OS creates AlertView
Watch WWDC 2014 Session 228 A Look Inside Presentation Controllers, they said
Behind the scenes, the framework creates a window on your app’s behalf, but this predates iOS 8 window rotation behavior, so this window is technically still in portrait.
We then add the action sheet to that window and mimic the transform hierarchy of the presenting view to get into the right orientation.
Use rootViewController approach
Some libraries, like FLEX, SIAlertView, … create new UIWindow and assign rootViewController to that window. This way orientation is reported to the rootViewController. They then simply add view to the rootViewController.view and handle orientation right inthe view controller.
Code extracted from FLEXViewExplorerViewController
UIWindow is a UIView
Since UIWindow is a UIView subclass, you can do many things you already know with UIView. For example, FLEX override pointInside:withEvent: to intercept touch through its toolbar
UIWindow in iOS 8
In iOS 8, Apple introduce Size Classes, and “Rotation is an animated bounds change”. And UIWindow is reported in device orientationWWDC 2014 Session 216 Building Adaptive Apps with UIKit
Trait Environments are a new protocol that are able to return their current Trait Collection, and these include Screens, Windows, View Controllers, and also Views.
All of these are able to return their current Trait Collection to you to use to determine how your interface should be laid out.
See Is [UIScreen mainScreen].bounds.size becoming orientation-dependent in iOS8?
UIScreen is now interface oriented:
[UIScreen bounds] now interface-oriented
[UIScreen applicationFrame] now interface-oriented
Status bar frame notifications are interface-oriented
Keyboard frame notifications are interface-oriented
Reference
Multiple UIWindowsTo create a new UIWindow over the main window
Advantages, problems, examples of adding another UIWindow to an iOS app?
The difference between a UIWindow and a UIView
Using multiple UIWindows in iOS applications
Technical Q&A QA1688 Why won’t my UIViewController rotate with the device?
After rotation UIView coordinates are swapped but UIWindow’s are not?
WWDC 2014 Session 214 View Controller Advancement in iOS 8
相关文章推荐
- GUI菜单练习
- quintic蓝牙芯片NVDS方法读写flash
- UIPopoverController的使用
- BAE Flask UEditor 使用七牛云
- HDU 1297 Children’s Queue(含整型大数模板)
- easyui中combobox的值改变onchang事件
- Unique Path
- 第五章:druid.io的应用场景
- easyui datagrid 中序列化后的日期格式化
- EasyUITreeGridMasterFile(EasyUITree大数据量一次性加载)
- Failed to issue method call: Unit mysql.service failed to load: No such file or directory解决的方式
- EasyUITreeMasterFile(EasyUITree大数据量一次性加载)
- Android自动化测试(UiAutomator)简要介绍 完整版本
- 百度ueditor编辑器插件开发之对话框-移动微模板插件
- Handling Technical Questions
- Android 使alertDialog.builder不会点击外面和按返回键消失
- COM模块三---根的形成和注册代理server(Building and Registering a Proxy DLL)
- Unique Binary Search Trees
- Handling Technical Questions
- String,StringBuffer与StringBuilder差异??