您的位置:首页 > 产品设计 > UI/UE

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


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:

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?


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

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


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)

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


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 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


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 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.


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 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


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 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


Reference

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: