【IOS】自動旋轉與調整大小xcode5以前&xcode5以後

//4.5版本開始啓用Autolayout了,能夠在file inspector 裏面 interface Builder Document欄下取消「Use Autolayout」的鉤選。 react

蘋果的產品iPad和iPhone都是支持自動旋轉的,於是咱們寫的程序也要支持兩種視圖:縱向和橫向。ios

默認狀況下,咱們寫的程序都是縱向的,就像前邊的幾個例子中那樣。若是運行之前寫的程序,當把模擬器旋轉,你會發現很不友好,有的控件看不見了。這個時候,自動旋轉就顯得頗有必要了。spring

一、咱們先不談如何實現自動旋轉,先講講如何讓程序知道它支持哪幾種旋轉。xcode

運行Xcode 4.2,新建一個Single View Application,程序名爲RotateTest,其餘設置以下圖:app

建立好工程後,打開的第一個頁面包含以下視圖:less

咱們能夠在這裏設置程序支持哪一種旋轉,只需選中那個按鈕。從上圖能夠看出,默認狀況下,iPhone程序不支持倒過來的旋轉,由於若是視圖是倒過來的,而此時忽然來電話,那麼會很不方便,由於頁面依然是倒過來的。可是,若是你建立了一個iPad程序,你回發現上圖四個按鈕都是選中的,即iPad程序默認支持全部旋轉。ide

注意,若是爲程序建立了多個View Controller,那麼每一個View Controller都要能夠設置所支持的旋轉,不過,新建的View Controller設置的值必須是主View Controller的子集。佈局

其實,咱們修改上圖中的按鈕,實質上修改的是咱們程序的plist文件,在這個工程中,是RotateTest-Info.plist文件,以下圖,展開這個文件,最下面顯示的就是所支持的旋轉:post

上面是設置支持選中的一種方法。咱們也能夠在代碼中設定所支持的旋轉。打開ViewController.m,找到shouldAutorotateToInterfaceOrientation方法,完整代碼以下:ui

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

上面的代碼代表,不支持倒轉(UIInterfaceOrientationPortraitUpsideDown)。

iOS中定義了四個表示方向的變量:

UIInterfaceOrientationPortrait
UIInterfaceOrientationPortraitUpsideDown
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight

若是iOS設置旋轉了,程序就會調用這個方向,若是返回YES就旋轉視圖,不然的話就不旋轉。若是你創建了一個iPad程序,這個方法就是簡單的返回YES。

二、既然咱們已經讓程序知道支持什麼旋轉了,下面講講如何實現。

在iOS中有三種方法能夠實現自動旋轉。

(1)最簡單的方法就是利用Xcode中的Size Inpector:

(2)在View所對應的ViewController.m中重寫willAnimateRotationToInterfaceOrientation方法,在這個方法中從新設置控件的大小與位置。

(3)再新建一個視圖,這樣,咱們有兩個視圖了,一個縱向,一個橫向。在這兩個視圖上設計好了以後,當旋轉時根據旋轉方向,調用相應的視圖。

三、如下是這三個方法的簡單使用。

3.1 使用Size Inpector實現自動旋轉:

① 單擊ViewController.xib,在打開的視圖區域拖放兩個Button在上面,分別命名爲「按鈕上」和「按鈕下」,頁面佈局以下圖:

圖中兩個按鈕在水平方向上是居中放置的。

② 運行程序,並將模擬器旋轉,對比一下旋轉先後的效果:

旋轉以後,「按鈕下」不見了。不過,「按鈕上」的座標和大小實際上是沒變的。

我如今想實現旋轉以後兩個按鈕仍是水平方向居中,而且仍是一個在頂端、一個在底端。爲實現這個,我要作如下工做:

③ 在View中選中「按鈕上」,打開Size Inspector,把左邊的紅實線改爲虛線:

④ 在View中選中「按鈕下」,打開Size Inspector,把左邊和上邊的紅實線改爲虛線,下邊的紅虛線改爲實線:

外圍的紅實線表示距離不變,例如上圖右中下方的紅實線就表示對應的控件與下方的距離不變,而其餘方向會自動調整。如今運行一下並旋轉模擬器,看看效果:

3.2 重寫willAnimateRotationToInterfaceOrientation方法,從新設置控件的大小與位置

① 首先先給這兩個按鈕添加Outlet映射到ViewController.h,名稱分別是button_1和button_2:

② 在ViewController.m中的@end以前添加如下代碼:

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval) duration {
    if (UIInterfaceOrientationIsPortrait(toInterfaceOrientation)) {
        button_1.frame = CGRectMake(124, 20, 72, 37);
        button_2.frame = CGRectMake(124, 403, 72, 37);
    } else {
        button_1.frame = CGRectMake(20, 131, 72, 37);
        button_2.frame = CGRectMake(388, 131, 72, 37);
    }
}

③ 運行,看看效果:

3.3 建立新視圖,旋轉時切換視圖:

① 咱們先建立原始視圖的副本,可是仍是在原來的ViewController中。單擊ViewController.xib,打開IB,在左邊的三個圖標中選中View圖標,若是用的是Mac Book,那麼按住Control鍵,若是是虛擬機,請按住Alt鍵。按住後按住鼠標左鍵,往下拖,鼠標會變成綠色的加號。注意新視圖跟原始圖是並列的,因此你要往正確的方向拖,而後鬆開鼠標,這樣就建立了原來視圖的副本:

② 調整新視圖爲橫向(Landscape):

選中新視圖,打開Attribute Inspector,在Orientation中選擇Landscape:

③ 調整新視圖中的按鈕的位置,你能夠按照本身的喜愛設置,這裏設置成以下所示:

④ 下面,咱們爲這兩個View創建Outlet映射,注意是View,而不是View上的控件。創建映射的方法都是同樣,兩個名稱分別是portrait和landscape:

⑤ 單擊ViewController.m,在@implementation那行代碼的下一行添加如下語句:

#define degreesToRadians(x) (M_PI*(x)/180.0)

⑥ 修改willAnimateRotationToInterfaceOrientation方法,以下:

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    if (toInterfaceOrientation == UIInterfaceOrientationPortrait) {
        self.view = self.portrait;
        self.view.transform = CGAffineTransformIdentity;
        self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(0));
        self.view.bounds = CGRectMake(0.0, 0.0, 320.0, 460.0);
    } else if(toInterfaceOrientation == UIInterfaceOrientationLandscapeLeft) {
        self.view = self.landscape;
        self.view.transform = CGAffineTransformIdentity;
        self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(-90));
        self.view.bounds = CGRectMake(0.0, 0.0, 480.0, 300.0);
    } else if(toInterfaceOrientation == UIInterfaceOrientationLandscapeRight) {
        self.view = self.landscape;
        self.view.transform = CGAffineTransformIdentity;
        self.view.transform = CGAffineTransformMakeRotation(degreesToRadians(90));
        self.view.bounds = CGRectMake(0.0, 0.0, 480.0, 300.0);
    }
}

⑦ 運行,查看效果:

四、小結

此次講了實現自動旋轉調整大小的三種方法,第一種只要點點鼠標,很簡單,但不適合複雜的視圖;第二種要從新設置控件的大小和位置,代碼量會比較大;第三種是建立兩種視圖,旋轉時調用不一樣的視圖,比較適合複雜的視圖。


http://www.raywenderlich.com/50319/beginning-auto-layout-tutorial-in-ios-7-part-2

https://www.captechconsulting.com/blog/jack-cox/ios-7-tutorial-series-auto-layout-xcode-5


iOS 7 Tutorial Series: Auto Layout in Xcode 5

by Jack Cox on Oct 01, 2013

iOS

iOS 7

Introduction

With the release of Xcode 5 and iOS 7 the need to learn, understand, and use Auto Layout become critical. This post reviews the changes to Auto Layout in Interface Builder (IB) in Xcode 5. This article is based on my experience using Auto Layout on a very large iPad app built using Xcode 4 and examining how I would build parts of that app if I had Xcode 5 from the start.

What is Auto Layout

Auto Layout is a constraint-based layout system available in iOS 6.0 and above. In Auto Layout you describe the relationship between views and iOS calculates the location and size of the views at runtime. This approach allows the layout to react to changes in screen and content size without requiring your code to change. It is important to note that Auto Layout is the only way that views are laid out in iOS, and while you may specify the layout using springs and struts in IB, but iOS always translates them to constraints at runtime. 

In iOS 6, Auto Layout was available and recommended, but not required. In iOS 7, Auto Layout has become more important, to the point of practically being required, because it facilitates the ability, provided by Dynamic Type, for users to select the font size to use in standard button, label, and text field controls, and then have the rest of the screen respond correctly to the change in font size.. 

A welcome change to Xcode 5 is greatly enhanced control over Auto Layout in Interface Builder. In Xcode 4, the creation of a slightly complicated view was close to impossible because Xcode did too much to ‘help’ the developer, but didn’t give the developer any way of correcting it’s ‘help’. Xcode 5 still has the ability to help the developer, but it only does so at the request of the developer. Yay! We humans are in control again.

Because of Xcode 4’s over-helping in IB, many developers frequently reverted two the two other ways to implement Auto Layout based views: Visual Format Language (VFL) and manually instantiating NSLayoutConstraint objects. Thankfully, because of the improvements in IB you’ll probably not be using these methods as much in the future. I’ve found that views that were impossible to build in Xcode 4 IB can now be created quickly and easily in Xcode 5.

Auto Layout uses NSLayoutConstraint objects to describe the relationship between views. A single NSLayoutConstraint object can only describe one relationship. To accurately specify the positioning of a view the constraints assigned to it must resolve to an X & Y position and a width & height. iOS evaluates all of the constraints in a view hierarchy, finds a valid solution where all of the constraints can be satisfied, and positions the views based on that solution. It will use priorities assigned to the views to arbitrate conflicts in the resolution of the constraints.  If you don’t specify a priority then iOS assigns the highest priority. If any one of positional or dimensional constraints are lacking on a view iOS will consider it an ambiguous layout and the position and size of the view will be indeterminate. If a view has conflicting relationship definitions, for example two constraints, with the same priority, that define the width, then iOS will log an error describing the conflict and discard one or more constraint that is causing the conflict. In some situations you may have multiple constraints that evaluate to identical answers, but iOS may still consider those to be conflicting.

Thinking in Auto Layout

One of the problems that have beset developers adopting Auto Layout is the need to change how you think about the position of our views. Before Auto Layout you thought about frames and bounds; size and position was everything. However, you must now think in terms of relationships rather than sizes.

I’ve seen two ways to think about relationships in Auto Layout: outside-in and inside-out. The outside-in way of thinking starts from the superview and applies relationships down the view hierarchy until you reach the lowest level UILabels, UIButtons, and other UIKit views. I’ve found that using this approach alone can easily lead to setting sizes on those lower level components, which violates the principle of thinking relationally.

The inside-out method starts by letting the lower level components specify their desired sizes via their intrinsic content size. Then their containing views are allowed to grow to contain their size or to limit their size based on external limitations (like the screen size). 

The truth is that both methods end up working together to define the layout. The resolution of a constraint equation works both from the inside-out and outside-in. Constraints on subviews can limit the size of the superview and constraints on a superview may limit the size of its subviews. 

There’s now a new way of thinking about laying out views in IB. In Xcode 4, as you placed or moved views in a xib, IB would continuously recalculate the constraints required to make the view as you had laid it out. This had the unfortunate side effect of IB constantly fighting what you wanted to do, and if you had manually created constraints it could delete them willy-nilly.  It also seemed to add constraints that were not necessary. Thankfully, IB doesn’t do that anymore.

Now, as you position views in IB it makes no assumptions about what constraints you want. You can get all of your views exactly where you want them (it still provides helpful guides to let you line things up). Once you’ve placed a view you can then ask IB to create the constraints to create the position you want, or you can specify those constraints yourself. If you create a constraint it will not remove it unless you ask it to. 

I’ve found the best approach to be:

  1. Place the views where you want them

  2. Manually add constraints to each view to give it the behavior you want

  3. Let IB add missing constraints

  4. Test in preview mode

 

 

Quick Tour of XCode 5 Interface Builder

When you open a xib file in XCode file you get a familiar looking screen. The most significant change is in the lower-right of the layout area. Apple has completely reworked the controls, shown in the Figure 1.

 

Figure 1: Auto Layout Controls

In the example for this blog, we’ll be defining constraints to layout a 10-button numeric keypad that resizes as it’s containing view resizes. In Xcode 4, this particular view was impossible to build using IB.

The Add New Alignment Constraint button (the left most button in Figure 2) in the controls brings up a menu that allows you to constrain views in relation to other views. These controls now allow you to specify a constant value to go with the constraint. 

 

Figure 2: Add New Alignment Constraints Popover

Each of the items in the popover menu allows you to define alignment constraints between two or more views.  For example, if you have two views selected and choose the Leading Edges checkbox, then IB will add a constraint to align the views’ leading edges. If you specify a number in the constant box to the right, it will adjust the constraint by the value of that constant.

When you add constraints to views using this method, you have the option of updating frames. By default, when you add a constraint this way, IB will not reposition the affected views to reflect the behavior of the constraints. The Update Frames control has 3 options:

  • None: No views are repositioned

  • Items of new constraints: Only those views that have constraints added will be repositioned.

  • All Frames in Container: All views in the container are repositioned, whether views were added or not.

Be aware that if you use items 2 and 3 while the constraints are still ambiguous your views may appear in odd places or become invisible.  I’ve found it best to wait until I think that I’ve fully specified the constraints before instructing IB to reposition the frames.

Many of these same relationships can be defined by control-clicking on a view in your layout and dragging the cursor to the related view. This works with any view in the hierarchy including the containing superview. In Figure 3, I’m connecting the buttons for 5 and 6.

 

Figure 3: Constraint Context Menu

The next control, the Add New Constraints control, in IB, show in Figure 4, adds new spacing and sizing constraints to your views. 

 

Figure 4: Add New Constraints

The top portion allows you to specify spacing between views. You can specify default values or specific values in each of the combo-boxes relating to a side of the view. If you’ve only selected one view, the spacing applies to relation between the selected view and its superview. The spacing combo boxes will also present values used in other constraints within this same view. 

The 2nd section allows you to specify the width and height of the selected views. I would think twice before using this type of control because it will quickly lead to thinking about frame sizes rather than relationships. If you’re only thinking about frame sizes you’ll end up creating a view that doesn’t size with new devices.

The 3rd section allows you to define relation ships between view widths and heights, and the 4th allows you to relate edges or centers of views.

The next popup menu is the cleanup menu, shown in Figure 5.  It helps you see what IB is thinking about constraints, request IB’s help, and to clean up general messes.

 

Figure 5: Constraint Cleanup

The Update Frames option will move all of the selected views to the positions specified by their constraints. If you have ambiguous views then this option may make views disappear or move out of bounds. This option makes no changes to your constraints.

The Update Constraints option does the opposite of Update Frames. It considers your manual placement of the selected views as gospel and updates constraints to match your layout. It does not add new constraints; it just updates the current constraints to match any manual movement of the view.

The next option, Add Missing Constraints, will add enough constraints to the selected views to remove any ambiguous layout problems. This is similar to what IB in Xcode 4 did when you manually moved a view.

The Reset to Suggested Constraints removes all of the constraints you’ve added to the selected views and does all of the thinking for you. If you liked IB in Xcode 4 then you’ll love this option. I suggest avoiding this option.

The Clear Constraints option removes all constraints from the selected views. This is a good way to get a do-over on a messed up layout.

The last group of options is similar to the first except they apply the action to all of the views in the selected view containers (view containers are the top level views).

Diagnosing Problems

IB in Xcode 5 provides some helpful diagnostic information to help you see if anything is wrong with your layout.

First, IB provides a helpful indicator, shown in Figure 6, on the view hierarchy if a view has problems. Click on that tiny red arrow to show a list of problems.

 

Figure 6: Problem Indicator

The list of problems can be anything from missing constraints, which is serious, to frames that are not where the constraints will place them. The misplaced view messages (shown in Figure 7) can be resolved by using one of the several Update Frames operations to relocate the views. You can use the Add Missing Constraints or Reset To Suggested Constraints options to fix missing constraints. Warning: resetting to suggested constraints could be dangerous to your layout and sanity.

 

Figure 7: Problem List

An orange dashed border, shown in Figure 8, on a selected view indicates that the view’s current frame does not match the location as computed by the current constraints. If you Update Frames on that view it will relocate to it’s computed position.

 

Figure 8: Misplaced Frames

A yellow solid frame on a view indicates that the view is under specified. See Figure 9 for an example, The red dashed rectangle shows the ambiguously computed frame for the view. You should take a close look at the view and determine which constraints need to be added. 

 

Figure 9: Missing Constraint

Red constraints, shown in Figure 10, indicate an over-specified and conflicting constraint configuration. You should determine which constraint is in error and delete it or lower its priority.

 

Figure 10: Constraint Conflict

Laying out a complex view

A practical example of the power of Xcode 5’s Interface Builder is its ability to layout complex view structures. In Xcode 4, it was close to impossible to maintain control of the constraints when doing complex views. If your view had more than a handful of sub-views things quickly got out of control. For this article we’ll show the full layout for a 10-button keypad.

One of the best practices recommended by Apple is to recite the behavior of the views then use those described behaviors to specify your constraints. 

In the spirit of that best practice, this paragraph will describe the behavior of the keypad. The keypad will be a 10 number keypad structured so that the keys resize to fit the view containing it.  All of the natural numbers (1-9) buttons will always be the same height & width and will have equal spacing between the buttons and the containing superview. The 0 button should be centered in the bottom of the view and extend to the edges of the view with the same spacing between it’s leading, trailing, and bottom edges as between each of the natural number buttons.  The 0 button will be the same height as all of the natural number keys.  

Notice that I didn’t specify any exact sizes, I’ll let Auto Layout figure out what the exact sizes will be at runtime.

To begin the example, drag 10 buttons onto the containing view and give each a text title corresponding to its number (Figure 11). You should place the numbers somewhat close to where you want them to end up in the final rendering. They don’t have to be exact; Auto Layout will remedy that soon. Don't let the buttons overlap because overlap tends to confuse IB.

Select all of the buttons in the view and then click on the Add New Constraints tool, as in Figure 11.

 

Figure 11: Layout Heights

Use the upper segment of the popover to set the spacing between all of the views to be the iOS standard spacing. If you want to change the spacing to something close or more spacious just change the ‘Standard’ value to your own specific value. Also, select the checkbox to make all of the views have Equal Heights. Notice that I’ve left the ‘Update Frames’ selection to None. If I were to update frames at this point the behavior would be unpredictable because all of the views still have ambiguous layout. After you’ve set the spacing and heights, press the ‘Add XX Constraints’ button to add those constraints to the layout.

The reason that the buttons are ambiguous is because we have not specified a width for them. We cannot do that in the first step because the 0 button’s width does not equal the other buttons.

To continue, the layout, select all of the natural number buttons and click the ‘Add New Constraints’ tool, as shown in Figure 12. In the tool, just select that the buttons have equal widths. This will add constraints to the buttons specifying that those buttons are all equal widths.

 

Figure 12: Layout View Widths

At this point it is safe to update the frames on the buttons in the container. I’ve selected the ‘All Frames in Container’ option for the update frames selection. This will move the buttons that you’ve laid out into their computed positions, shown in Figure 13. Each of the constraints on the views will be displayed with an icon indicating the type of constraint. If you select a single view it will display all constraints that are associated with that view. For example, in the view below I’ve selected the 4 button. IB shows the constraints on the 4 button and the 5 button because the height and width of the 5 button are constrained to equal the height and width of the 2 button.

 

Figure 13: Constraint Display

Conclusion

Apple has listened to its developers and produced a very usable and powerful tool for manipulating view constraints in Xcode 5. You will not have to fight it or avoid it as with prior versions of Xcode, but you should keep in mind some key principles for Auto Layout:

  • Think relationally; don’t think about frames and sizes.

  • Don’t think linearly; Auto Layout doesn’t evaluate constraints in order. They are all considered equally, and conflicts are resolved via priority.

  • Don’t over-specify constraints. Just say as little as possible to communicate the layout and no more.

  • Avoid letting IB define constraints for you. Unless your view is very simple, IB will probably get it wrong.

相關文章
相關標籤/搜索