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

相关文章
相关标签/搜索