天天看點

1102 - iOS◍ 文檔: View Programming Guide for iOS -- iOS的視圖程式設計指南 第三章 view Views

參考連結:https://www.cnblogs.com/patientAndPersist/p/3171311.html

别人翻譯得很好了,後面的有一些我是直接複制粘貼的

Views

--Because view objects are the main way your application interacts with the user, they have many responsibilities. Here are just a few:

     view是客戶與手機進行互動的主要方式,但是window才是傳遞事件的擔當者。然後,一個view的主要職責有:

● Layout and subview management --布局和管理子view方面有:

  • A view defines its own default resizing behaviors in relation to its parent view.

       view定義自己的 相對于父視圖的 預設的“尺寸調整行為”

  • A view can manage a list of subviews.

       view可以管理一堆子view

  • A view can override the size and position of its subviews as needed.

        view可以複寫子 view的大小和位置。

  • A view can convert points in its coordinate system to the coordinate systems of other views or the window.

        view可以轉換不同坐标系間的“點單元”

● Drawing and animation  -- 繪圖與動畫效果:

  • A view draws content in its rectangular area.

       view在自己的矩形中繪制内容

  • Some view properties can be animated to new values.

       view中的部分屬性可以由一個值動畫過渡到另一個值

● Event handling -- 事件處理

  • A view can receive touch events.

       view可以接受觸摸事件

  • A view participates in the responder chain.

       view參與響應者鍊

--This chapter focuses on the steps for creating, managing, and drawing views and for handling the layout and management of view hierarchies. For information about how to handle touch events (and other events) in your views, see Event Handling Guide for iOS.

    這一章主要是講view的建立、管理、繪制、布局處理以及視圖層的管理。更多關于view中觸摸事件的管理,搜尋Event Handling Guide for iOS

Creating and Configuring View Objects -- 建立和配置view

--You create views as self-contained objects either programmatically or using Interface Builder, and then you assemble them into view hierarchies for use.

    IB或者程式設計方式

Creating View Objects Using Interface Builder -- 用IB建立view

--The simplest way to create views is to assemble them graphically using Interface Builder. From Interface Builder, you can add views to your interface, arrange those views into hierarchies, configure each view’s settings, and connect view-related behaviors to your code. Because Interface Builder uses live view objects—that is, actual instances of the view classes—what you see at design time is what you get at runtime. You then save those live objects in a nib file, which is a resource file that preserves the state and configuration of your objects.

      IB畫出來的view是一個活着的view執行個體,是以你可以在畫的時候就可以看到同樣的在app運作期的效果。然後你是把這個view以nib file的形式存起來,然後app真正運作時就把這個view真實的複活出來 。

--You usually create nib files in order to store an entire view hierarchy for one of your application’s view controllers. The top level of the nib file usually contains a single view object that represents your view controller’s view. (The view controller itself is typically represented by the File’s Owner object.) The top-level view should be sized appropriately for the target device and contain all of the other views that are to be presented. It is rare to use a nib file to store only a portion of your view controller’s view hierarchy.

    每一個vc都管理自己的一個視圖層次,而一個nib file 通常用來儲存一個視圖層次,而不是單單一個view。

--When using nib files with a view controller, all you have to do is initialize the view controller with the nib file information. The view controller handles the loading and unloading of your views at the appropriate times. However, if your nib file is not associated with a view controller, you can load the nib file contents manually using an

NSBundle

or

UINib

object, which use the data in the nib file to reconstitute your view objects.

     如果你的nib file和一個vc關聯,那麼vc負責從nib file上加載和解除安裝view。如果你沒有與vc關聯,那麼你就可以使用

NSBundle

or

UINib

執行個體來從nib file中擷取關于view的資訊,然後将這些view的集合 複活

--For more information about how to use Interface Builder to create and configure your views, see Interface Builder User Guide. For information about how view controllers load and manage their associated nib files, see Creating Custom Content View Controllers in View Controller Programming Guide for iOS. For more information about how to load views programmatically from a nib file, see Nib Files in Resource Programming Guide.

     關于如何使用IB、vc如何與nib file關聯加載解除安裝、如何從nib file中加載一個view、自己看對應的超連結

Creating View Objects Programmatically -- 程式設計方式建立view

--If you prefer to create views programmatically, you can do so using the standard allocation/initialization pattern. The default initialization method for views is the

initWithFrame:

method, which sets the initial size and position of the view relative to its (soon-to-be-established) parent view. For example, to create a new generic

UIView

object, you could use code similar to the following:

     allocation/initialization pattern.是執行個體的記憶體配置設定和初始化模式,可以打超連結看一下。view預設的初始化方法是

initWithFrame:

,你調用該初始化方法設定view在父view中的位置和尺寸。示例如下:

CGRect  viewRect = CGRectMake(0, 0, 100, 100);
UIView* myView = [[UIView alloc] initWithFrame:viewRect];
           

--Note: Although all views support the

initWithFrame:

method, some may have a preferred initialization method that you should use instead. For information about any custom initialization methods, see the reference documentation for the class.

     注意:

initWithFrame:

初始化方法是所有view都有的方法,但不是唯一的選擇,有些view提供了更好的初始化方法,使用時考慮一下。

--After you create a view, you must add it to a window (or to another view in a window) before it can become visible. For information on how to add views to your view hierarchy, see Adding and Removing Subviews.

       在建立一個view之後,你必須把它直接或間接地添加到window裡面,關于如何增删子view,看下面。

Setting the Properties of a View -- 設定一個view的屬性

--The

UIView

class has several declared properties for controlling the appearance and behavior of the view. These properties are for manipulating the size and position of the view, the view’s transparency, its background color, and its rendering behavior. All of these properties have appropriate default values that you can change later as needed. You can also configure many of these properties from Interface Builder using the Inspector window.

      你可以通過UIVIew的聲明屬性來修改view的位置、透明度、背景顔色、和渲染行為。

--Table 3-1 lists some of the more commonly used properties (and some methods) and describes their usage. Related properties are listed together so that you can see the options you have for affecting certain aspects of the view.

      UIView的部分聲明屬性以及方法的使用。

Table 3-1  Usage of some key view properties

Properties Usage

alpha

,

hidden

,

opaque

不透明度,隐藏,是否不透明

--These properties affect the opacity of the view. The

alpha

and

hidden

properties change the view’s opacity directly.

  alpha

hidden屬性,直接影響UIView的透明度

--The

opaque

property tells the system how it should composite your view. Set this property to

YES

if your view’s content is fully opaque and therefore does not reveal any of the underlying view’s content. Setting this property to

YES

improves performance by eliminating unnecessary compositing operations.

    設定遮光度paque為true可以提供渲染效率,因為這樣目前view底下的view的組成操作會被取消。

bounds

,

frame

,

center

,

transform

邊界,架構,中心點,形變
--These properties affect the size and position of the view. The

center

and

frame

properties represent the position of the view relative to its parent view. The

frame

also includes the size of the view. The

bounds

property defines the view’s visible content area in its own coordinate system.

   center

frame屬性是以父視圖的坐标為坐标系,bounds是自身的本地坐标系

--The

transform

property is used to animate or move the entire view in complex ways. For example, you would use a transform to rotate or scale the view. If the current transform is not the identity transform, the

frame

property is undefined and should be ignored.

For information about the relationship between the

bounds

,

frame

, and

center

properties, see The Relationship of the Frame, Bounds, and Center Properties. For information about how transforms affect a view, see Coordinate System Transformations.

    超連結看Frame, Bounds, and Center Properties屬性的差別,Coordinate System Transformations.看view如何形變

autoresizingMask

,

autoresizesSubviews

尺寸自動調整
--These properties affect the automatic resizing behavior of the view and its subviews. The

autoresizingMask

property controls how a view responds to changes in its parent view’s bounds. The

autoresizesSubviews

property controls whether the current view’s subviews are resized at all.

  autoresizingMask

屬性控制view如何響應父view的bounds變化。

autoresizesSubviews屬性控制view的子view是不是尺寸自動調整的。

contentMode

,

contentStretch

,

contentScaleFactor

内容模式、内容拉伸、内容縮放因子

--These properties affect the rendering behavior of content inside the view. The

contentMode

and

contentStretch

properties determine how the content is treated when the view’s width or height changes. The

contentScaleFactor

property is used only when you need to customize the drawing behavior of your view for high-resolution screens.

  contentMode 和 contentStretch屬性用于視圖内容如何響應view的寬高發生改變,

contentScaleFactor屬性用于處理高分辨率螢幕的渲染view的行為。

--For more information on how the content mode affects your view, see Content Modes. For information about how the content stretch rectangle affects your view, see Stretchable Views. For information about how to handle scale factors, see Supporting High-Resolution Screens In Views in Drawing and Printing Guide for iOS.

     關于内容模式看Content Modes;關于view的拉伸,看Stretchable Views;關于高分辨率螢幕的縮放,看Drawing and Printing Guide for iOS中的Supporting High-Resolution Screens In Views。

gestureRecognizers

,

userInteractionEnabled

,

multipleTouchEnabled

,

exclusiveTouch

手勢識别器、使用者互動使能、多點觸摸使能、專一觸摸使能

--These properties affect how your view processes touch events. The

gestureRecognizers

property contains gesture recognizers attached to the view. The other properties control what touch events the view supports.

  gestureRecognizers屬性用于關聯手勢識别器,其他屬性也是觸摸事件的相關支援。

--For information about how to respond to events in your views, see Event Handling Guide for iOS.

     關于觸摸事件的響應,百度Event Handling Guide for iOS

backgroundColor

,

subviews

,

drawRect:

method,

layer

, (

layerClass

method)

背景顔色、子view、繪制矩形方法

--These properties and methods help you manage the actual content of your view. For simple views, you can set a background color and add one or more subviews. The

subviews

property itself contains a read-only list of subviews, but there are several methods for adding and rearranging subviews. For views with custom drawing behavior, you must override the

drawRect:

method.

  subviews屬性傳回的是一組子view清單,但是是隻讀的,你可以複寫drawRect:來自定義視圖的繪制行為。

--For more advanced content, you can work directly with the view’s Core Animation

layer

. To specify an entirely different type of layer for the view, you must override the

layerClass

method.

   動畫屬性的相關設定,你必須要複寫layer類裡面的相關方法。

--For information about the basic properties common to all views, see UIView Class Reference. For more information about specific properties of a view, see the reference documentation for that view.

Tagging Views for Future Identification -- 給view加标簽 供查找子view使用

--The

UIView

class contains a

tag

property that you can use to tag individual view objects with an integer value. You can use tags to uniquely identify views inside your view hierarchy and to perform searches for those views at runtime. (Tag-based searches are faster than iterating the view hierarchy yourself.) The default value for the

tag

property is

.

   UIView有一

個tag屬性,你可以指派整數值給該屬性,來唯一辨別一個view執行個體。這樣尋找views層中的某一個view時,效率比周遊整個views層要高。

--To search for a tagged view, use the

viewWithTag:

method of

UIView

. This method performs a depth-first search of the receiver and its subviews. It does not search superviews or other parts of the view hierarchy. Thus, calling this method from the root view of a hierarchy searches all views in the hierarchy but calling it from a specific subview searches only a subset of views.

    使用UIView中的

viewWithTag:

方法來擷取子views數組中帶有某tag的子view,這是用深度搜尋算法實作的。

Creating and Managing a View Hierarchy -- 建立和管理視圖層

--Managing view hierarchies is a crucial part of developing your application’s user interface. The organization of your views influences both the visual appearance of your application and how your application responds to changes and events. For example, the parent-child relationships in the view hierarchy determine which objects might handle a specific touch event. Similarly, parent-child relationships define how each view responds to interface orientation changes.

      視圖的組織既影響了app可見的外觀,也影響了你的app如何響應事件以及app狀态的變化。例如父子關系中,就可以指定某object處理某觸摸事件。

--Figure 3-1 shows an example of how the layering of views creates the desired visual effect for an application. In the case of the Clock application, the view hierarchy is composed of a mixture of views derived from different sources. The tab bar and navigation views are special view hierarchies provided by the tab bar and navigation controller objects to manage portions of the overall user interface. Everything between those bars belongs to the custom view hierarchy that the Clock application provides.

     圖 3-1 顯示了”視圖的分層機制“如何建立應用app所需的視圖效果。在時鐘app中,視圖的層次結構是由不同來源的各種視圖的混合物組成的。标簽欄和導航視圖是特殊的視圖層次結構, 它們由标簽欄和導航控制器對象提供,用來管理整個使用者界面的一部分。你可以在标簽欄裡自定義你的視圖層,而這種結構的支援,由時鐘app提供。

Figure 3-1  Layered views in the Clock application

1102 - iOS◍ 文檔: View Programming Guide for iOS -- iOS的視圖程式設計指南 第三章 view Views

--There are several ways to build view hierarchies in iOS applications, including graphically in Interface Builder and programmatically in your code. The following sections show you how to assemble your view hierarchies and, having done that, how to find views in the hierarchy and convert between different view coordinate systems.

      在iOS應用程式裡有好幾種方式可以建立視圖層次結構,包括在IB裡的圖形化設計和在代碼實作。接下來的章節顯示你可以如何合成視圖層次結構,以及當你完成層次後如何在層次結構裡查找這些視圖,以及如何在不同坐标系統裡互相轉換。

Adding and Removing Subviews -- 添加和删除子視圖

--Interface Builder is the most convenient way to build view hierarchies because you assemble your views graphically, see the relationships between the views, and see exactly how those views will appear at runtime. When using Interface Builder, you save your resulting view hierarchy in a nib file, which you load at runtime as the corresponding views are needed.

     使用IB建立視圖層次,你的view 層次是存儲在nib file裡面的,nib file是在運作期按需加載的。

--If you prefer to create your views programmatically instead, you create and initialize them and then use the following methods to arrange them into hierarchies:

     程式設計方式建立view 層次的話,你需要用到以下方法:

  • To add a subview to a parent, call the

    addSubview:

    method of the parent view. This method adds the subview to the end of the parent’s list of subviews.

       在父view 中調用

addSubview:

方法來建立子view,并自動添加到view層次中了

  • To insert a subview in the middle of the parent’s list of subviews, call any of the

    insertSubview:...

    methods of the parent view. Inserting a subview in the middle of the list visually places that view behind any views that come later in the list.

       想在父視圖的子視圖清單中部插入一個子視圖,你可以調用

insertSubview:...

方法;然後該子視圖就會出現子視圖清單的中間了。    

  • To reorder existing subviews inside their parent, call the

    bringSubviewToFront:

    ,

    sendSubviewToBack:

    , or

    exchangeSubviewAtIndex:withSubviewAtIndex:

    methods of the parent view. Using these methods is faster than removing the subviews and reinserting them.

       想要重排序子視圖的位置,那麼你可以調用父視圖的

bringSubviewToFront:

,

sendSubviewToBack:

, 和

exchangeSubviewAtIndex:withSubviewAtIndex:

方法,就會執行把子視圖放在最前、最後、交換位置的操作,這比插入、删除子視圖的效率要高。

  • To remove a subview from its parent, call the

    removeFromSuperview

    method of the subview (not the parent view).

        從父視圖中移除子視圖,是調用子視圖的

removeFromSuperview

方法,注意是子視圖的方法,不是父視圖。

--When adding a subview to its parent, the subview’s current frame rectangle denotes its initial position inside the parent view. A subview whose frame lies outside of its superview’s visible bounds is not clipped by default. If you want your subview to be clipped to the superview’s bounds, you must explicitly set the

clipsToBounds

property of the superview to

YES

.

     當添加一個子視圖到父視圖中時,子視圖的frame是參考父視圖的frame的坐标系的。而且,預設是不裁剪子視圖内容來适應父視圖的bounds邊界的。你可以使用父視圖的

clipsToBounds

屬性為true,來使子視圖裁剪适應。

--One place where you might add subviews to a view hierarchy is in the

loadView

or

viewDidLoad

methods of a view controller. If you are building your views programmatically, you put your view creation code in the

loadView

method of your view controller. Whether you create your views programmatically or load them from a nib file, you could include additional view configuration code in the

viewDidLoad

method.

     一般來講,程式設計方式添加子視圖,是在vc的

loadView

viewDidLoad

方法中寫添加代碼的。

Listing 3-1 shows the

viewDidLoad

method of the

TransitionsViewController

class from the UIKit Catalog (iOS): Creating and Customizing UIKit Controls sample application. The

TransitionsViewController

class manages the animations associated with transitioning between two views. The application’s initial view hierarchy (consisting of a root view and toolbar) is loaded from a nib file. The code in the

viewDidLoad

method subsequently creates the container view and image views used to manage the transitions. The purpose of the container view is to simplify the code needed to implement the transition animations between the two image views. The container view has no real content of its own.

    清單3-1的代碼來自于超連結UIKit Catalog (iOS): Creating and Customizing UIKit Controls的示例中的部分代碼,是例子中的

TransitionsViewController的部分代碼,展示在

viewDidLoad

方法中添加子視圖到父視圖中的關鍵代碼。

示例實作了兩個view之間的動畫過渡效果。

   示例中的

TransitionsViewController是一個vc容器,由根視圖和工具欄組成。

 容器視圖的作用主要是為了簡化兩個子view之間動畫過渡時的代碼。

Listing 3-1  Adding views to an existing view hierarchy

                       示例代碼展示如何添加現存view到視圖層次裡面

- (void)viewDidLoad

{
    [super viewDidLoad];

    self.title = NSLocalizedString(@"TransitionsTitle", @"");

    // create the container view which we will use for transition animation (centered horizontally)

    CGRect frame = CGRectMake(round((self.view.bounds.size.width - kImageWidth) / 2.0), kTopPlacement, kImageWidth, kImageHeight);

    self.containerView = [[[UIView alloc] initWithFrame:frame] autorelease];

    [self.view addSubview:self.containerView];

    // The container view can represent the images for accessibility.

    [self.containerView setIsAccessibilityElement:YES];

    [self.containerView setAccessibilityLabel:NSLocalizedString(@"ImagesTitle", @"")];

    // create the initial image view

    frame = CGRectMake(0.0, 0.0, kImageWidth, kImageHeight);

    self.mainView = [[[UIImageView alloc] initWithFrame:frame] autorelease];

    self.mainView.image = [UIImage imageNamed:@"scene1.jpg"];

    [self.containerView addSubview:self.mainView];

    // create the alternate image view (to transition between)

    CGRect imageFrame = CGRectMake(0.0, 0.0, kImageWidth, kImageHeight);

    self.flipToView = [[[UIImageView alloc] initWithFrame:imageFrame] autorelease];

    self.flipToView.image = [UIImage imageNamed:@"scene2.jpg"];

}
           

--Important: Superviews automatically retain their subviews, so after embedding a subview it is safe to release that subview. In fact, doing so is recommended because it prevents your application from retaining the view one time too many and causing a memory leak later. Just remember that if you remove a subview from its superview and intend to reuse it, you must retain the subview again. The

removeFromSuperview

method autoreleases a subview before removing it from its superview. If you do not retain the view before the next event loop cycle, the view will be released.

  移除子view的時候,記得釋放子視圖的資源,但是現在swift已經自動釋放了。

--For more information about Cocoa memory management conventions, see Advanced Memory Management Programming Guide.

   更多關于記憶體管理的内容,參考超連結

--When you add a subview to another view, UIKit notifies both the parent and child views of the change. If you implement custom views, you can intercept these notifications by overriding one or more of the

willMoveToSuperview:

,

willMoveToWindow:

,

willRemoveSubview:

,

didAddSubview:

,

didMoveToSuperview

, or

didMoveToWindow

methods. You can use these notifications to update any state information related to your view hierarchy or to perform additional tasks.

     當你添加一個子view到父view中時,UIKit會同時通知父view和子view該“添加”事件。是以你可以在你的子類化view中複寫view的

willMoveToSuperview:

,

willMoveToWindow:

,

willRemoveSubview:

,

didAddSubview:

,

didMoveToSuperview

, or

didMoveToWindow

這些方法之一,然後就可以在添加期間的響應時期做相關的操作。

--After creating a view hierarchy, you can navigate it programmatically using the

superview

and

subviews

properties of your views. The

window

property of each view contains the window in which that view is currently displayed (if any). Because the root view in a view hierarchy has no parent, its

superview

property is set to

nil

. For views that are currently onscreen, the window object is the root view of the view hierarchy.

     建立完一個視圖層次結構之後,你可以通過程式使用視圖的 

superview

 和 

subviews 屬性來使用它。每個視圖的 

window 屬性包含了該視窗,視窗裡顯示目前的所有視圖(如果有)。因為視圖層次結構裡的根視圖沒有父視圖,它的superview屬性被設定為nil. 對于那些正在螢幕上的所有視圖,視窗對象是該視圖層次結構裡的根視圖。

Hiding Views -- 隐藏視圖

--To hide a view visually, you can either set its

hidden

property to

YES

or change its

alpha

property to

0.0

. A hidden view does not receive touch events from the system. However, hidden views do participate in autoresizing and other layout operations associated with the view hierarchy. Thus, hiding a view is often a convenient alternative to removing views from your view hierarchy, especially if you plan to show the views again at some point soon.

      隐藏的view不接收事件的傳遞,但是仍然參與自動布局。

Important: If you hide a view that is currently the first responder, the view does not automatically resign its first responder status. Events targeted at the first responder are still delivered to the hidden view. To prevent this from happening, you should force your view to resign the first responder status when you hide it. For more information about the responder chain, see Event Handling Guide for iOS.

        view即便隐藏了,也不會修改自己第一響應者的身份,是以你要手動修改。

--If you want to animate a view’s transition from visible to hidden (or the reverse), you must do so using the view’s

alpha

property. The

hidden

property is not an animatable property, so any changes you make to it take effect immediately.

hidden

屬性沒有動畫效果,

alpha

屬性有動畫效果

Locating Views in a View Hierarchy -- 定位視圖層中的視圖

--There are two ways to locate views in a view hierarchy:

兩個方法定位視圖,一是直接建立時複制引用,二是用view的tag标簽,可以兩者并用。

  • Store pointers to any relevant views in an appropriate location, such as in the view controller that owns the views.
  • Assign a unique integer to each view’s

    tag

    property and use the

    viewWithTag:

    method to locate it.

--Storing references to relevant views is the most common approach to locating views and makes accessing those views very convenient. If you used Interface Builder to create your views, you can connect objects in your nib file (including the File’s Owner object that represents the managing controller object) to one another using outlets. For views you create programmatically, you can store references to those views in private member variables. Whether you use outlets or private member variables, you are responsible for retaining the views as needed and then releasing them as well. The best way to ensure objects are retained and released properly is to use declared properties.

     建議将子view聲明為私有屬性。

--Tags are a useful way to reduce hard-coded dependencies and support more dynamic and flexible solutions. Rather than storing a pointer to a view, you could locate it using its tag. Tags are also a more persistent way of referring to views. For example, if you wanted to save the list of views that are currently visible in your application, you would write out the tags of each visible view to a file. This is simpler than archiving the actual view objects, especially in situations where you are tracking only which views are currently visible. When your application is subsequently loaded, you would then re-create your views and use the saved list of tags to set the visibility of each view, and thereby return your view hierarchy to its previous state.

    使用tag來尋找view有助于提供性能。

Translating, Scaling, and Rotating Views -- 轉換、縮放、和旋轉視圖

--Every view has an associated affine transform that you can use to translate, scale, or rotate the view’s content. View transforms alter the final rendered appearance of the view and are often used to implement scrolling, animations, or other visual effects.

       形變最終會改變view的外觀。

The

transform

property of

UIView

contains a

CGAffineTransform

structure with the transformations to apply. By default, this property is set to the identity transform, which does not modify the appearance of the view. You can assign a new transform to this property at any time. For example, to rotate a view by 45 degrees, you could use the following code:

      形變必須是恒等變換,數學上的知識,形變的值是

CGAffineTransform

結構體裡面的值,下面是形變的簡單示例代碼:

// M_PI/4.0 is one quarter of a half circle, or 45 degrees.

CGAffineTransform xform = CGAffineTransformMakeRotation(M_PI/4.0);

self.view.transform = xform;
           

--Applying the transform in the preceding code to a view would rotate that view clockwise about its center point. Figure 3-2 shows how this transformation would look if it were applied to an image view embedded in an application.

        給視圖應用以上代碼的變換可以将視圖圍繞它的中心點旋轉45度。圖3-2 顯示了該變換應用于形變視圖的效果。

Figure 3-2  Rotating a view 45 degrees

1102 - iOS◍ 文檔: View Programming Guide for iOS -- iOS的視圖程式設計指南 第三章 view Views

--When applying multiple transformations to a view, the order in which you add those transformations to the

CGAffineTransform

structure is significant. Rotating the view and then translating it is not the same as translating the view and then rotating it. Even if the amounts of rotation and translation are the same in each case, the sequence of the transformations affects the final results. In addition, any transformations you add are applied to the view relative to its center point. Thus, applying a rotation factor rotates the view around its center point. Scaling a view changes the width and height of the view but does not change its center point.

      組合

CGAffineTransform

結構體的值的順序不同,那麼形變的效果也不一樣。

--For more information about creating and using affine transforms, see Transforms in Quartz 2D Programming Guide.

     更多關于形變的資訊,參考超連結。

Converting Coordinates in the View Hierarchy                -- 轉換視圖層中的坐标系

--At various times, particularly when handling events, an application may need to convert coordinate values from one frame of reference to another. For example, touch events report the location of each touch in the window’s coordinate system but view objects often need that information in the view’s local coordinate system. The

UIView

class defines the following methods for converting coordinates to and from the view’s local coordinate system:

     在不同的事件,特别是當處理事件時,應用程式可能需要轉換坐标值,從一個架構引用到另一個。 比如,觸摸事件報告的是每個觸摸在視窗坐标系統裡的位置,但是視圖對象常常需要該位置在視圖的内部坐标系統中的值。 UIView 類定義了以下方法,用來從視圖的内部坐标系統轉換坐标或從别的坐标系統轉換到視圖的内部坐标系統:

  • convertPoint:fromView:

  • convertRect:fromView:

  • convertPoint:toView:

  • convertRect:toView:

--The

convert...:fromView:

methods convert coordinates from some other view’s coordinate system to the local coordinate system (bounds rectangle) of the current view. Conversely, the

convert...:toView:

methods convert coordinates from the current view’s local coordinate system (bounds rectangle) to the coordinate system of the specified view. If you specify

nil

as the reference view for any of the methods, the conversions are made to and from the coordinate system of the window that contains the view.

      convert...:fromView: 方法把其它視圖坐标系的坐标轉換為目前視圖的内部坐标系(邊界矩形)坐标。相反,convert...:toView:方法則把目前坐标系坐标轉換為其他的視圖坐标系坐标。 如果你給任何方法指定了nil值作為引用視圖,該轉換是包含該視圖的視窗坐标系統中轉換而來,或者是轉換到該視窗坐标系統中去。

--In addition to the

UIView

conversion methods, the

UIWindow

class also defines several conversion methods. These methods are similar to the

UIView

versions except that instead of converting to and from a view’s local coordinate system, these methods convert to and from the window’s coordinate system.

      除了UIView 轉換方法,UIWindow 類也定義了一些轉換方法。這些方法跟UIView的方法相似,隻除了這些方法是從視窗坐标系統中轉換而來,或者轉換到視窗坐标系統中去。

  • convertPoint:fromWindow:

  • convertRect:fromWindow:

  • convertPoint:toWindow:

  • convertRect:toWindow:

--When converting coordinates in rotated views, UIKit converts rectangles under the assumption that you want the returned rectangle to reflect the screen area covered by the source rectangle. Figure 3-3 shows an example of how rotations can cause the size of the rectangle to change during a conversion. In the figure, an outer parent view contains a rotated subview. Converting a rectangle in the subview’s coordinate system to the parent’s coordinate system yields a rectangle that is physically larger. This larger rectangle is actually the smallest rectangle in the bounds of

outerView

that completely encloses the rotated rectangle.

     當你在被旋轉的視圖裡轉換坐标時,UIKit在這樣的假設下轉換前的矩形---假設你想要傳回的矩形反映了被源矩形覆寫的螢幕區域。圖3-3 顯示了一個例子---在轉換過程中旋轉如何導緻矩形尺寸的改變。在圖中,一個外部父視圖包含了一個已旋轉的子視圖。轉換在子視圖坐标系統裡的一個子視圖到父視圖坐标系統,生成了一個外形上更大的矩形。該被放大的矩形實際上是在外部視圖(outerView)邊界裡完全包含被旋轉矩形的最小矩形。

Figure 3-3  Converting values in a rotated view

1102 - iOS◍ 文檔: View Programming Guide for iOS -- iOS的視圖程式設計指南 第三章 view Views

Adjusting the Size and Position of Views at Runtime -- 在運作期調整視圖的尺寸和位置

--Whenever the size of a view changes, the size and position of its subviews must change accordingly. The

UIView

class supports both the automatic and manual layout of views in a view hierarchy. With automatic layout, you set the rules that each view should follow when its parent view resizes, and then forget about resizing operations altogether. With manual layout, you manually adjust the size and position of views as needed.

    無論何時一個視圖的尺寸發生了改變,它的子視圖的尺寸和位置也必須相應的發生改變。

UIView 類同時支援在一個視圖層次結構裡的視圖的自動和手動布局。

 在自動布局裡,你可以這樣設定規則:每個視圖,當它的父視圖重新調整尺寸時,也跟着改變,然後兒子們全都忽略關于重新調整尺寸的操作。對于手動布局,你根據需要手動調整視圖的尺寸和位置。

Being Prepared for Layout Changes -- 為布局的改變做準備

--Layout changes can occur whenever any of the following events happens in a view:

    如果發生以下事件,則可以引起視圖布局的改變

  • The size of a view’s bounds rectangle changes.

        bounds矩形的尺寸改變

  • An interface orientation change occurs, which usually triggers a change in the root view’s bounds rectangle.

        裝置方位的改變

  • The set of Core Animation sublayers associated with the view’s layer changes and requires layout.

        核心動畫圖層的改變

  • Your application forces layout to occur by calling the

    setNeedsLayout

    or

    layoutIfNeeded

    method of a view.

        你通過調用

setNeedsLayout

or

layoutIfNeeded

方法強行将布局改變

  • Your application forces layout by calling the

    setNeedsLayout

    method of the view’s underlying layer object.

     你可以調用view的底層的layer的

    setNeedsLayout

    方法來強制app更新布局。

Handling Layout Changes Automatically Using Autoresizing Rules     -- 使用布局自動調整規則

--When you change the size of a view, the position and size of any embedded subviews usually needs to change to account for the new size of their parent. The

autoresizesSubviews

property of the superview determines whether the subviews resize at all. If this property is set to

YES

, the view uses the

autoresizingMask

property of each subview to determine how to size and position that subview. Size changes to any subviews trigger similar layout adjustments for their embedded subviews.

    當你改變了視圖的尺寸,所有子視圖通常都需要改變他們的位置和尺寸,以适應它們父視圖的新尺寸。 父視圖的 

autoresizesSubviews 屬性決定了子視圖是否需要重新調整尺寸。 如果該屬性被設定為YES, 視圖使用每個子視圖的autoresizingMask 屬性來決定如何調整該子視圖的尺寸和位置。 任何子視圖的尺寸發生改變同時又觸發它們的子視圖也跟着改變以适應變化。

--For each view in your view hierarchy, setting that view’s

autoresizingMask

property to an appropriate value is an important part of handling automatic layout changes. Table 3-2 lists the autoresizing options you can apply to a given view and describes their effects during layout operations. You can combine constants using an OR operator or just add them together before assigning them to the

autoresizingMask

property. If you are using Interface Builder to assemble your views, you use the Autosizing inspector to set these properties.

    對于視圖層次結構裡的每個視圖,給子view的 autoresizingMask 屬性設定一個合适的值是處理自動布局改變的一個很重要的部分。你可以使用OR運算符組合這些常量或隻需要在把它們發送給autoresizingMask屬性之前把它們加到一起。如果你使用界面生成器來組合(assemble)你的視圖,你可以使用Autosizing inspector 來設定這些屬性。

Table 3-2  Autoresizing mask constants

Autoresizing mask Description

UIViewAutoresizingNone

----The view does not autoresize. (This is the default value.)

視圖不會自動調整尺寸(這是預設值)

UIViewAutoresizingFlexibleHeight

--The view’s height changes when the superview’s height changes. If this constant is not included, the view’s height does not change.

當父視圖的高度發生改變時,視圖的高度也跟着改變。

UIViewAutoresizingFlexibleWidth

--The view’s width changes when the superview's width changes. If this constant is not included, the view’s width does not change.

當父視圖的寬度發生改變時,子視圖的寬度也發生改變。

UIViewAutoresizingFlexibleLeftMargin

--The distance between the view’s left edge and the superview’s left edge grows or shrinks as needed. If this constant is not included, the view’s left edge remains a fixed distance from the left edge of the superview.

視圖左邊緣和父視圖的左邊緣之間的距離根據需要放大或縮小。如果不包含該常量,視圖的左邊緣跟父視圖的左邊緣之間的距離保持一個固定值。

UIViewAutoresizingFlexibleRightMargin

--The distance between the view’s right edge and the superview’s right edge grows or shrinks as needed. If this constant is not included, the view’s right edge remains a fixed distance from the right edge of the superview.

視圖右邊緣和父視圖的右邊緣之間的距離根據需要放大或縮小。如果不包含該常量,視圖的右邊緣跟父視圖的右邊緣之間的距離保持一個固定值。

UIViewAutoresizingFlexibleBottomMargin

--The distance between the view’s bottom edge and the superview’s bottom edge grows or shrinks as needed. If this constant is not included, the view’s bottom edge remains a fixed distance from the bottom edge of the superview.

視圖下邊緣和父視圖的下邊緣之間的距離根據需要放大或縮小。如果不包含該常量,視圖的下邊緣跟父視圖的下邊緣之間的距離保持一個固定值。

UIViewAutoresizingFlexibleTopMargin

--The distance between the view’s top edge and the superview’s top edge grows or shrinks as needed. If this constant is not included, the view’s top edge remains a fixed distance from the top edge of the superview.

視圖上邊緣和父視圖的上邊緣之間的距離根據需要放大或縮小。如果不包含該常量,視圖的上邊緣跟父視圖的上邊緣之間的距離保持一個固定值。

--Figure 3-4 shows a graphical representation of how the options in the autoresizing mask apply to a view. The presence of a given constant indicates that the specified aspect of the view is flexible and may change when the superview’s bounds change. The absence of a constant indicates that the view’s layout is fixed in that aspect. When you configure a view that has more than one flexible attribute along a single axis, UIKit distributes any size changes evenly among the corresponding spaces.

      圖3-4 顯示了這些自動調整尺寸蒙闆(autoresizing mask)應用于視圖之後的圖形化效果。下面給出的常量,表明視圖的這方面是靈活的并可能在父視圖邊界發生變化時跟着改變。沒有給出的常量表明視圖的布局在這方面是固定的。當你沿着一個單軸(single axis)配置擁有多個靈活的屬性的視圖時,UIKit把所有的尺寸變化均勻地分布在相關空間裡。

Figure 3-4  View autoresizing mask constants

1102 - iOS◍ 文檔: View Programming Guide for iOS -- iOS的視圖程式設計指南 第三章 view Views

--The easiest way to configure autoresizing rules is using the Autosizing controls in the Size inspector of Interface Builder. The flexible width and height constants from the preceding figure have the same behavior as the width and size indicators in the Autosizing controls diagram. However, the behavior and use of margin indicators is effectively reversed. In Interface Builder, the presence of a margin indicator means that the margin has a fixed size and the absence of the indicator means the margin has a flexible size. Fortunately, Interface Builder provides an animation to show you how changes to the autoresizing behaviors affect your view.

         配置自動調整尺寸最簡單的方法是使用IB界面生成器中Size inspector的Autosizing controls項。上圖中靈活的長寬常量跟在Autosizing controls圖中的width and size indicators 有着相同的行為。然而, margin indicators的行為和使用卻相反。在界面生成器裡,margin indicator的存在表明一個固定值,不存在該值則表明margin有一個靈活的值。 幸運的是,界面生成器提供了一個動畫,用來給你顯示如何改變autoresizing 行為才會對你的視圖産生影響。

Important: If a view’s

transform

property does not contain the identity transform, the frame of that view is undefined and so are the results of its autoresizing behaviors.

        如果視圖的transform 屬性值不是恒等變換,該視圖的frame是未定義的,而且它的自動調整尺寸行為的結果也是未定義的。

--After the automatic autoresizing rules for all affected views have been applied, UIKit goes back and gives each view a chance to make any necessary manual adjustments to its superview. For more information about how to manage the layout of views manually, see Tweaking the Layout of Your Views Manually.

        當對所有被影響的視圖應用自動調整尺寸規則之後,UIKit傳回每個視圖并給一個機會來 針對其父視圖變化 做必要的手動調整。關于如何手動管理視圖的布局的更多資訊,請看“Tweaking the Layout of Your Views Manually.”

Tweaking the Layout of Your Views Manually -- 手動調整視圖的布局

--Whenever the size of a view changes, UIKit applies the autoresizing behaviors of that view’s subviews and then calls the

layoutSubviews

method of the view to let it make manual changes. You can implement the

layoutSubviews

method in custom views when the autoresizing behaviors by themselves do not yield the results you want. Your implementation of this method can do any of the following:

       任何時候當view的尺寸發生變化時,UIKit都會給view的子視圖應用自動調整尺寸行為,然後調用視圖的 ★ layoutSubviews方法來讓它做手動改變。當它們的自動調整尺寸行為不能産生你想要的結構時,你可以在自定義的視圖裡實作layoutSubviews方法。你對該方法的實作可以完成以下任何事情:

  • Adjust the size and position of any immediate subviews.

         調整任何目前的子視圖的尺寸和位置。

  • Add or remove subviews or Core Animation layers.

         添加或删除子視圖或核心動畫層。

  • Force a subview to be redrawn by calling its

    setNeedsDisplay

    or

    setNeedsDisplayInRect:

    method.

       通過調用自己的

setNeedsDisplay

 或 

setNeedsDisplayInRect: 方法來強制子視圖重新繪制。

--One place where applications often lay out subviews manually is when implementing a large scrollable area. Because it is impractical to have a single large view for its scrollable content, applications often implement a root view that contains a number of smaller tile views. Each tile represents a portion of the scrollable content. When a scroll event happens, the root view calls its

setNeedsLayout

method to initiate a layout change. Its

layoutSubviews

method then repositions the tile views based on the amount of scrolling that occurred. As tiles scroll out of the view’s visible area, the

layoutSubviews

method moves the tiles to the incoming edge, replacing their contents in the process.

       應用程式常常手動布局子視圖的地方是當你實作一個大的可滾動區域時。因為隻給它的滾動區域設定一個大的單一視圖是不切實際的,應用程式常常實作一個根視圖,在根視圖裡包含一定數量的較小的瓷磚(tile)視圖。每個瓷磚代表可滾動内容的一部分。 當一個滾動事件發生時,根視圖調用它的setNeedsLayout 方法來初始化一個布局改變。 然後它的layoutSubviews方法在發生的滾動數量基礎上重新定位這些瓷磚視圖。 當瓷磚滾出了視圖的可見區域時,layoutSubviews方法把這些瓷磚移到進入的邊緣,在程序中替換它們的内容。

--When writing your layout code, be sure to test your code in the following ways:

     當你編寫你的布局代碼時,請確定你的代碼通過了以下測試:

  • Change the orientation of your views to make sure the layout looks correct in all supported interface orientations.

        改變你的視圖方向,確定布局在所有支援的界面方向上都顯示正确。

  • Make sure your code responds appropriately to changes in the height of the status bar. When a phone call is active, the status bar height increases in size, and when the user ends the call, the status bar decreases in size.

       確定你的代碼能對狀态欄高度的變化做出适當的響應。 當有來電時,狀态欄高度尺寸增大,當使用者切斷通話時,狀态欄縮減它的尺寸。

For information about how autoresizing behaviors affect the size and position of your views, see Handling Layout Changes Automatically Using Autoresizing Rules. For an example of how to implement tiling, see the ScrollViewSuite sample.

       關于自定調整尺寸行為如何影響視圖的尺寸和位置的資訊,請看“Handling Layout Changes Automatically Using Autoresizing Rules.” 關于如何實作tiling的例子,請看ScrollViewSuite。

Modifying Views at Runtime -- 在運作期修改視圖

--As applications receive input from the user, they adjust their user interface in response to that input. An application might modify its views by rearranging them, changing their size or position, hiding or showing them, or loading an entirely new set of views. In iOS applications, there are several places and ways in which you perform these kinds of actions:

      當應用程式接收到使用者輸入時,會調整使用者界面來響應那個輸入。應用程式可能通過重新整理,改變界面的尺寸或位置,隐藏或顯示界面,或載入一個完整的視圖新集來修改界面上的視圖。在iOS應用程式中,有很多地方和很多方法可以讓你執行這類操作:

--In a view controller:

 在視圖控制器中修改:

  • A view controller has to create its views before showing them. It can load the views from a nib file or create them programmatically. When those views are no longer needed, it disposes of them.

       視圖控制器必須在顯示view之前建立view。它能從一個nib檔案載入視圖,或者通過程式建立它們。當這些視圖不再被需要時,vc要負責丢棄它們

  • When a device changes orientations, a view controller might adjust the size and position of views to match. As part of its adjustment to the new orientation, it might hide some views and show others.

       當裝置改變方向時,視圖控制器可能調整視圖的尺寸和位置來比對該方向。為了應對新方向做出調整,vc可能隐藏一些視圖和顯示一些其它視圖。

  • When a view controller manages editable content, it might adjust its view hierarchy when moving to and from edit mode. For example, it might add extra buttons and other controls to facilitate editing various aspects of its content. This might also require the resizing of any existing views to accommodate the extra controls.

        當視圖控制器管理一個可編輯内容時,當移入或移出編輯模式時,vc可能調整它的視圖層次結構。比如,vc可能添加額外的按鈕和其它一些控件來友善編輯vc内容的各個方面。 這樣也可能要求對 任何已經存在的視圖 做出尺寸調整,以容納額外的控件。

--In animation blocks:

在動畫塊中修改:

  • When you want to transition between different sets of views in your user interface, you hide some views and show others from inside an animation block.

       當你想要在使用者界面上的不同視圖集之間互相過渡時,你可以在一個動畫塊裡隐藏一些視圖和顯示其它視圖。

  • When implementing special effects, you might use an animation block to modify various properties of the view. For example, to animate changes to the size of a view, you would change the size of its frame rectangle.

       當你想實作一些特殊效果時,你可能需要使用一個動畫塊來修改視圖中的各種屬性。比如,動畫視圖的尺寸變化,你也可能改變view的矩形和尺寸。

--Other ways:

其它方式修改: 

  • When touch events or gestures occur, your interface might respond by loading a new set of views or changing the current set of views. For information about handling events, see Event Handling Guide for iOS.

        當觸摸事件或手勢發生時,你的界面可以通過載入一個新的視圖集或改變目前的視圖集來響應。 關于處理事件的資訊,請看Event Handling Guide for iOS.

  • When the user interacts with a scroll view, a large scrollable area might hide and show tile subviews. For more information about supporting scrollable content, see Scroll View Programming Guide for iOS.

       當使用者跟一個滾動視圖互動時,一個巨大的可滾動區可能隐藏,并顯示瓷磚子視圖。關于支援可滾動内容的更多資訊,請看Scroll View Programming Guide for iOS.

  • When the keyboard appears, you might reposition or resize views so that they do not lie underneath the keyboard. For information about how to interact with the keyboard, see Text Programming Guide for iOS.
  •  當鍵盤出現時,你可能對視圖做重新定位和定尺寸,這樣它們在不會被隐藏在鍵盤下面。 關于如何跟鍵盤互動的資訊,請看Text, Web, and Editing Programming Guide for iOS。

--View controllers are a common place to initiate changes to your views. Because a view controller manages the view hierarchy associated with the content being displayed, it is ultimately responsible for everything that happens to those views. When loading its views or handling orientation changes, the view controller can add new views, hide or replace existing ones, and make any number of changes to make the views ready for the display. And if you implement support for editing your view’s content, the

setEditing:animated:

method in

UIViewController

gives you a place to transition your views to and from their editable versions.

    視圖控制器是開始改變視圖的一個常用的地方。因為一個視圖控制器管理着視圖層次,該層次跟要顯示的内容相關聯,它最終負責對那些視圖發生的所有事情。 當載入vc的視圖或處理方向變換時,視圖控制器能添加新視圖,隐藏或替換存在的視圖,并對準備顯示的視圖做任何數量的改變。 并且如果你實作支援可編輯視圖的内容, UIViewController裡的

setEditing:animated: 方法給你提供了一個地方,讓你的視圖從它們可編輯版本中過渡過來,或從可編輯版本過渡到視圖中去。

--Animation blocks are another common place to initiate view-related changes. The animation support built into the

UIView

class makes it easy to animate changes to view properties. You can also use the

transitionWithView:duration:options:animations:completion:

or

transitionFromView:toView:duration:options:completion:

methods to swap out entire sets of views for new ones.

      動畫塊是開始做視圖相關改變的另一個常用地方。 支援在

UIView類裡内建動畫讓動畫視圖屬性的各種改變變得容易。你還可以使用

transitionWithView:duration:options:animations:completion: 或 

transitionFromView:toView:duration:options:completion: 方法來給新的視圖集合換出整個視圖集合。

--For more information about animating views and initiating view transitions, see Animations. For more information on how you use view controllers to manage view-related behaviors, see View Controller Programming Guide for iOS.

    關于動畫視圖和初始化視圖過渡的更多資訊,請看 “Animations.” 關于你如何使用視圖控制器來管理視圖相關的行為的更多資訊,請看View Controller Programming Guide for iOS.

Interacting with Core Animation Layers -- 與視圖動畫層互動

--Each view object has a dedicated Core Animation layer that manages the presentation and animation of the view’s content on the screen. Although you can do a lot with your view objects, you can also work directly with the corresponding layer objects as needed. The layer object for the view is stored in the view’s

layer

property.

    每個視圖對象都有一個專用的核心動畫層,該動畫層管理螢幕上視圖内容的呈現和動畫。 盡管你可以用視圖對象完成很多事情,你也可以根據需要直接跟相關的層對象一起工作。 視圖的圖層對象被存儲在視圖的

layer 屬性裡。

Changing the Layer Class Associated with a View -- 改變與視圖相關的圖層

--The type of layer associated with a view cannot be changed after the view is created. Therefore, each view uses the

layerClass

class method to specify the class of its layer object. The default implementation of this method returns the

CALayer

class and the only way to change this value is to subclass, override the method, and return a different value. You can change this value to use a different kind of layer. For example, if your view uses tiling to display a large scrollable area, you might want to use the

CATiledLayer

class to back your view.

      跟視圖相關聯的層類型在視圖被建立後就不能被更改。 是以,每次視圖使用layerClass 類方法來指定圖層對象的類。該方法的預設實作傳回

CALayer 類,而且改變該值的唯一方法是子類化UIView,重載該方法,并傳回一個不同值。你可以使用不同的layer類型來指派給

layerClass

屬性,例如你想要大的滑動視圖時,指派CATiledLayer給你的view的

layerClass

屬性即可。

Implementation of the

layerClass

method should simply create the desired

Class

object and return it. For example, a view that uses tiling would have the following implementation for this method:

     實作layerClass 方法應該簡單建立一個所需的Class 對象,并傳回它。比如,一個支援OpenGL ES繪圖的視圖可能對該方法做以下實作:

+ (Class)layerClass

{
    return [CATiledLayer class];
}
           

--Each view calls its

layerClass

method early in its initialization process and uses the returned class to create its layer object. In addition, the view always assigns itself as the delegate of its layer object. At this point, the view owns its layer and the relationship between the view and layer must not change. You must also not assign the same view as the delegate of any other layer object. Changing the ownership or delegate relationships of the view will cause drawing problems and potential crashes in your application.

    每個視圖在它的初始化過程早期調用它的layerClass方法,并使用layerClass傳回的類來建立view的圖層對象。 另外,視圖總是作為它的層對象的代理。 在這時,視圖擁有它的層,并且視圖和圖層之間的關系決不能改變。你也決不能讓同一個視圖成為任何其它圖層對象的代理。改變視圖的所屬關系或代理關系将導緻應用程式發生繪圖問題以及潛在崩潰。

For more information about the different types of layer objects provided by Core Animation, see Core Animation Reference Collection.

     關于由核心動畫提供的圖層對象的不同類型的更多資訊,請看Core Animation Reference Collection.

Embedding Layer Objects in a View -- 在視圖中嵌入 圖層對象

--If you prefer to work primarily with layer objects instead of views, you can incorporate custom layer objects into your view hierarchy as needed. A custom layer object is any instance of

CALayer

that is not owned by a view. You typically create custom layers programmatically and incorporate them using Core Animation routines. Custom layers do not receive events or participate in the responder chain but do draw themselves and respond to size changes in their parent view or layer according to the Core Animation rules.

     如果你更喜歡主要使用圖層對象來代替視圖工作,你可以根據需要在你的視圖層次結構裡納入自定義圖層對象。自定義圖層對象是任何CALayer 的執行個體,它不屬于任何視圖。你通常通過程式建立自定義視圖,并用核心動畫程式納入它們。自定義圖層不接收事件或參與響應鍊,但是它們确實繪制它們自己并響應它們父視圖或跟核心動畫規則相關的層的尺寸改變。

Listing 3-2 shows an example of the

viewDidLoad

method from a view controller that creates a custom layer object and adds it to its root view. The layer is used to display a static image that is animated. Instead of adding the layer to the view itself, you add it to the view’s underlying layer.

     清單3-2 顯示了一個例子,該例子是一個視圖控制器中的viewDidLoad方法,它建立并添加一個自定義圖層到它的根視圖。該層用于顯示一個被動畫的靜态圖檔。 不添加該層到視圖本身,而是添加到視圖下面的層上。

Listing 3-2  Adding a custom layer to a view

- (void)viewDidLoad {

    [super viewDidLoad];

    // Create the layer.

    CALayer* myLayer = [[CALayer alloc] init];

    // Set the contents of the layer to a fixed image. And set

    // the size of the layer to match the image size.

    UIImage layerContents = [[UIImage imageNamed:@"myImage"] retain];

    CGSize imageSize = layerContents.size;

    myLayer.bounds = CGRectMake(0, 0, imageSize.width, imageSize.height);

    myLayer = layerContents.CGImage;

    // Add the layer to the view.

    CALayer*    viewLayer = self.view.layer;

    [viewLayer addSublayer:myLayer];

    // Center the layer in the view.

    CGRect        viewBounds = backingView.bounds;

    myLayer.position = CGPointMake(CGRectGetMidX(viewBounds), CGRectGetMidY(viewBounds));

 

    // Release the layer, since it is retained by the view's layer

    [myLayer release];

}
           

--You can add any number of sublayers and arrange them into sublayer hierarchies, if you want. However, at some point, those layers must be attached to the layer object of a view.

        如果你需要,你可以添加任何數量的子圖層并把它們整理到子圖層的層次結構裡。然而,在一些時候,那些圖層必須被連接配接到一個視圖的圖層對象上。

--For information on how to work with layers directly, see Core Animation Programming Guide.

      關于如何跟層直接工作的資訊,請看Core Animation Programming Guide.

Defining a Custom View -- 自定義視圖

--If the standard system views do not do exactly what you need, you can define a custom view. Custom views give you total control over the appearance of your application’s content and how interactions with that content are handled.

       如果标準系統視圖不能提供你所需要的,你可以定義一個自定義視圖。自定義視圖讓你完全控制app的外觀,以及處理客戶跟視圖内容的互動。

Note: If you are using OpenGL ES to do your drawing, you should use the

GLKView

class instead of subclassing

UIView

. For more information about how to draw using OpenGL ES, see OpenGL ES Programming Guide.

        注意:OpenGL ES技術不是使用UIView,而是使用

GLKView

類,看超連結

Checklist for Implementing a Custom View -- 實作自定義視圖的清單

--The job of a custom view is to present content and manage interactions with that content. The successful implementation of a custom view involves more than just drawing and handling events, though. The following checklist includes the more important methods you can override (and behaviors you can provide) when implementing a custom view:

   一個自定義視圖的工作是呈現内容并管理與該内容的互動。 但是,一個自定義視圖的成功實作不僅僅涉及繪制和處理事件。以下清單包含了更多你實作一個自定義視圖時可以重載的重要方法(以及你可以提供的行為):

  • Define the appropriate initialization methods for your view:

         為你的視圖定義合适的初始化方法:

        • For views you plan to create programmatically, override the

initWithFrame:

method or define a custom initialization method.

            對于你打算以程式設計方式建立的視圖,那就重寫initWithFrame: 方法,或定義一個自定義初始化方法。

        • For views you plan to load from nib files, override the

initWithCoder:

method. Use this method to initialize your view and put it into a known state.

          對于你打算從nib檔案載入的視圖,那就重寫initWithCoder: 方法。使用該方法來初始化你的視圖并把它放入已知的狀态。

  • Implement a

    dealloc

    method to handle the cleanup of any custom data.

          實作一個 

dealloc方法來處理任何自定義資料的清理工作。

  • To handle any custom drawing, override the

    drawRect:

    method and do your drawing there.

           要想處理任何自定義繪制,那就重寫drawRect:方法,并在那完成繪圖。

  • Set the

    autoresizingMask

    property of the view to define its autoresizing behavior.

         設定視圖的autoresizingMask 屬性來定義它的自動調整尺寸行為。

  • If your view class manages one or more integral subviews, do the following:

       如果你的視圖類管理一個或多個基本的子視圖,完成以下事情:

        • Create those subviews during your view’s initialization sequence.

            在你的視圖初始化序列期間建立那些子視圖。

        • Set the

autoresizingMask

property of each subview at creation time.

            在建立時為每個子視圖設定的autoresizingMask 屬性。

        • If your subviews require custom layout, override the

layoutSubviews

method and implement your layout code there.

            如果你的子視圖要求自定義布局,重載 

layoutSubviews 方法并在這裡實作你的布局代碼。

  • To handle touch-based events, do the following:

          要想處理基于觸摸的事件,那就完成以下事情: 

        • Attach any suitable gesture recognizers to the view by using the

addGestureRecognizer:

method.

           通過使用addGestureRecognizer: 方法來把合适的手勢識别器連接配接到視圖。

        • For situations where you want to process the touches yourself, override the

touchesBegan:withEvent:

,

touchesMoved:withEvent:

,

touchesEnded:withEvent:

, and

touchesCancelled:withEvent:

methods. (Remember that you should always override the

touchesCancelled:withEvent:

method, regardless of which other touch-related methods you override.)

        如果你想自己處理觸摸事件,重寫

touchesBegan:withEvent:

,

touchesMoved:withEvent:

touchesEnded:withEvent:

, 以及 

touchesCancelled:withEvent: 方法。無論你重載了哪些與觸摸事件相關的方法,你都必須重寫touchesCancelled:withEvent:

方法

  • If you want the printed version of your view to look different from the onscreen version, implement the

    drawRect:forViewPrintFormatter:

    method. For detailed information about how to support printing in your views, see Drawing and Printing Guide for iOS.

          如果你想讓你的視圖列印版本跟螢幕上的版本不同,實作drawRect:forViewPrintFormatter: 方法。 關于如何在視圖裡支援列印的詳情,請看Drawing and Printing Guide for iOS.

--In addition to overriding methods, remember that there is a lot you can do with the view’s existing properties and methods. For example, the

contentMode

and

contentStretch

properties let you change the final rendered appearance of your view and might be preferable to redrawing the content yourself. In addition to the

UIView

class itself, there are many aspects of a view’s underlying

CALayer

object that you can configure directly or indirectly. You can even change the class of the layer object itself.

        除了使用子類來重寫方法,有很多視圖已經存在的屬性和方法也可以完成很多事情。比如, 

contentMode

 和 

contentStretch 屬性讓你改變視圖的最終渲染外形,并可能是你自己重新繪制内容更好。除了

UIView本身,視圖的背景CALayer對象有很多方面你可以直接或間接配置。你甚至可以自己改變圖層對象的類。

--For more information about the methods and properties of the view class, see UIView Class Reference.

     關于視圖類的方法和屬性的更多資訊,請看UIView Class Reference.

Initializing Your Custom View -- 初始化自定義的視圖

--Every new view object you define should include a custom

initWithFrame:

initializer method. This method is responsible for initializing the class at creation time and putting your view object into a known state. You use this method when creating instances of your view programmatically in your code.

      每一個你自定義的視圖對象都應該包含一個自定義的initWithFrame: 初始化方法。該方法負責在建立時自定義該類并把視圖對象放入一個已知的狀态。當你在代碼裡通過程式建立視圖的執行個體時,你将使用該方法。

--Listing 3-3 shows a skeletal implementation of a standard

initWithFrame:

method. This method calls the inherited implementation of the method first and then initializes the instance variables and state information of the class before returning the initialized object. Calling the inherited implementation is traditionally performed first so that if there is a problem, you can abort your own initialization code and return

nil

.

     清單 3-3 顯示了一個标準initWithFrame:方法的架構實作。該方法首先調用該方法的被繼承(super)實作,然後在傳回初始化對象之前初始化執行個體變量和類的狀态資訊。調用被繼承的實作通常都首先被執行,這樣如果有問題,你可以退出你自己的初始化代碼并傳回nil。

Listing 3-3  Initializing a view subclass

- (id)initWithFrame:(CGRect)aRect {

    self = [super initWithFrame:aRect];

    if (self) {

          // setup the initial properties of the view

          ...

       }

    return self;

}
           

--If you plan to load instances of your custom view class from a nib file, you should be aware that in iOS, the nib-loading code does not use the

initWithFrame:

method to instantiate new view objects. Instead, it uses the

initWithCoder:

method that is part of the

NSCoding

protocol.

      如果你計劃從一個nib檔案載入你的自定義視圖執行個體,你應該意識到在iOS裡,nib載入的代碼不适宜用initWithFrame:方法來執行個體化新的視圖對象。作為替代,它使用

initWithCoder: 方法來初始化,該方法是NSCoding 方法的一部分。

--Even if your view adopts the

NSCoding

protocol, Interface Builder does not know about your view’s custom properties and therefore does not encode those properties into the nib file. As a result, your own

initWithCoder:

method should perform whatever initialization code it can to put the view into a known state. You can also implement the

awakeFromNib

method in your view class and use that method to perform additional initialization.

     即使你的視圖采用了NSCoding協定,界面生成器也不會知道你的視圖的自定義屬性,是以沒有把那些屬性編碼到nib檔案。是以,你自己的initWithCoder: 方法,執行的是 “它能夠把視圖放入一個已知狀态的”初始化代碼。 你還可以在你的視圖類裡實作awakeFromNib 方法并使用該方法來執行額外的初始化。

Implementing Your Drawing Code                                              -- 實作繪圖代碼

--For views that need to do custom drawing, you need to override the

drawRect:

method and do your drawing there. Custom drawing is recommended only as a last resort. In general, if you can use other views to present your content, that is preferred.

     對于那些需要完成自定義繪制的視圖,你需要重寫

drawRect: 方法,并在那裡書寫你的繪制代碼。自定義繪制建議隻能作為最後的手段。 通常,如果你可以使用其它視圖來呈現你的内容,那樣做更好。

--The implementation of your

drawRect:

method should do exactly one thing: draw your content. This method is not the place to be updating your application’s data structures or performing any tasks not related to drawing. It should configure the drawing environment, draw your content, and exit as quickly as possible. And if your

drawRect:

method might be called frequently, you should do everything you can to optimize your drawing code and draw as little as possible each time the method is called.

       你的drawRect: 方法實作應該隻做好一件事:繪制你的内容。該方法不是更新你的應用程式資料結構或執行任何跟繪制無關的任務。它應該配置繪圖環境,繪制内容,以及盡可能快的退出來。并且如果你的drawRect:方法會經常被調用,你應該做你能做的一切來優化你的繪圖代碼,讓它每次調用時盡可能少的繪圖。

--Before calling your view’s

drawRect:

method, UIKit configures the basic drawing environment for your view. Specifically, it creates a graphics context and adjusts the coordinate system and clipping region to match the coordinate system and visible bounds of your view. Thus, by the time your

drawRect:

method is called, you can begin drawing your content using native drawing technologies such as UIKit and Core Graphics. You can get a pointer to the current graphics context using the

UIGraphicsGetCurrentContext

function.

     當你調用視圖的drawRect: 方法之前,UIKit為你的視圖配置了基本的繪圖環境。 特别是,它建立了一個圖形上下文以及調整了坐标系統并裁減區域讓其跟坐标系相比對,讓視圖的邊界可見。 是以,當drawRect: 方法被調用時,你可以使用本地繪圖技術比如UIKit和Core Graphics開始繪制你的内容。你可以用UIGraphicsGetCurrentContext 函數擷取一個指向目前圖形上下文的指針。

Important: The current graphics context is valid only for the duration of one call to your view’s

drawRect:

method. UIKit might create a different graphics context for each subsequent call to this method, so you should not try to cache the object and use it later.

       重要提示:目前圖形上下文隻在調用視圖的drawRect: 方法期間有效。 UIKit可能在每次調用此方法建立一個不同的圖形上下文,是以你不應該嘗試緩存該對象并在以後使用。

--Listing 3-4 shows a simple implementation of a

drawRect:

method that draws a 10-pixel-wide red border around the view. Because UIKit drawing operations use Core Graphics for their underlying implementations, you can mix drawing calls, as shown here, to get the results you expect.

     清單 3-4 顯示了drawRect: 方法的一個簡單實作, 它繪制了一個10個像素寬的紅邊框視圖。 因為UIKit繪圖操作使用核心圖形(Core Graphics)來完成它們的背景實作, 你可以混合各種繪圖調用,正如這裡所示,來達到你期望的結果。

Listing 3-4  A drawing method

- (void)drawRect:(CGRect)rect {

    CGContextRef context = UIGraphicsGetCurrentContext();

    CGRect    myFrame = self.bounds;
 
    // Set the line width to 10 and inset the rectangle by

    // 5 pixels on all sides to compensate for the wider line.

    CGContextSetLineWidth(context, 10);

    CGRectInset(myFrame, 5, 5);

    [[UIColor redColor] set];

    UIRectFrame(myFrame);

}
           

--If you know that your view’s drawing code always covers the entire surface of the view with opaque content, you can improve system performance by setting the

opaque

property of your view to

YES

. When you mark a view as opaque, UIKit avoids drawing content that is located immediately behind your view. This not only reduces the amount of time spent drawing but also minimizes the work that must be done to composite your view with other content. However, you should set this property to

YES

only if you know your view’s content is completely opaque. If your view cannot guarantee that its contents are always opaque, you should set the property to

NO

.

      如果你知道你視圖的繪圖代碼永遠用不透明的内容覆寫整個視圖表明,你就可以通過設定視圖的 

opaque 屬性為YES來提高系統的性能。當你把視圖示記為不透明時,UIKit避免繪制那些是以在視圖後面的内容。這樣做不僅減少了繪圖的總時間,還減少了視圖必須跟别的内容的合成工作。然而,隻要你知道你的視圖内容是完全不透明的,那麼你就應該設定該屬性為YES。 如果你的視圖不能保證都是不透明的,你應該設定它為NO。

--Another way to improve drawing performance, especially during scrolling, is to set the

clearsContextBeforeDrawing

property of your view to

NO

. When this property is set to

YES

, UIKIt automatically fills the area to be updated by your

drawRect:

method with transparent black before calling your method. Setting this property to

NO

eliminates the overhead for that fill operation but puts the burden on your application to fill the update rectangle passed to your

drawRect:

method with content.

       另一個提供繪圖性能的方法,特别是滾動期間,是設定視圖的clearsContextBeforeDrawing 屬性為NO。 當這個屬性被設定為YES, UIKit在調用你的drawRect: 方法之前自動用透明的黑色背景填充整個區域。設定該屬性為NO消除了填充操作的開銷(overhead),但是把負擔加到應用程式填充更新矩形,并把内容傳遞給drawRect: 方法。

Responding to Events                                                -- 響應事件

--View objects are responder objects—instances of the

UIResponder

class—and are therefore capable of receiving touch events. When a touch event occurs, the window dispatches the corresponding event object to the view in which the touch occurred. If your view is not interested in an event, it can ignore it or pass it up the responder chain to be handled by a different object.

      視圖對象都是響應者對象---都是UIResponder類的一個執行個體---是以能接收觸摸事件。當一個觸摸事件發生時,視窗發派相關的事件對象給觸摸事件發生的視圖。 如果你的視圖對事件不感興趣,view能忽視事件或者把事件傳遞到響應者鍊由别的對象來處理。

--In addition to handling touch events directly, views can also use gesture recognizers to detect taps, swipes, pinches, and other types of common touch-related gestures. Gesture recognizers do the hard work of tracking touch events and making sure that they follow the right criteria to qualify them as the target gesture. Instead of your application having to track touch events, you can create the gesture recognizer, assign an appropriate target object and action method to it, and install it on your view using the

addGestureRecognizer:

method. The gesture recognizer then calls your action method when the corresponding gesture occurs.

        除了直接處理觸摸事件,視圖還能使用手勢識别器來偵察點選(taps), 滑動(swipes), 捏合(piches), 以及其他類型的常用觸摸相關的手勢。 手勢觸摸完成追蹤觸摸事件的困難工作,并確定它們遵守正确的标準來識别出它們的目标手勢。 app不需要追蹤觸摸事件,你隻需要建立手勢識别器(gesture recognizer), 配置設定一個适當的目标對象和操作方法給手勢識别器, 然後使用

addGestureRecognizer: 方法來把手勢識别裝載進你的視圖,即可。當發生相應的手勢時,便會自動執行該操作方法。

--If you prefer to handle touch events directly, you can implement the following methods for your view, which are described in more detail in Event Handling Guide for iOS:

如果你更喜歡直接處理觸摸事件,你可以在視圖裡實作以下方法,它們在Event Handling Guide for iOS 裡有着更詳細的描述:

  • touchesBegan:withEvent:

  • touchesMoved:withEvent:

  • touchesEnded:withEvent:

  • touchesCancelled:withEvent:

--The default behavior for views is to respond to only one touch at a time. If the user puts a second finger down, the system ignores the touch event and does not report it to your view. If you plan to track multi-finger gestures from your view’s event-handler methods, you need to enable multitouch events by setting the

multipleTouchEnabled

property of your view to

YES

.

      視圖的預設行為是一次隻響應一個觸摸事件。 如果使用者按下第二個手指,系統忽視該觸摸事件,并不向視圖報告。 如果你計劃從視圖的事件處理器方法中追蹤多手指手勢,你需要設定視圖的multipleTouchEnabled 屬性來啟動多觸摸事件。

--Some views, such as labels and images, disable event handling altogether initially. You can control whether a view is able to receive touch events by changing the value of the view’s

userInteractionEnabled

property. You might temporarily set this property to

NO

to prevent the user from manipulating the contents of your view while a long operation is pending. To prevent events from reaching any of your views, you can also use the

beginIgnoringInteractionEvents

and

endIgnoringInteractionEvents

methods of the

UIApplication

object. These methods affect the delivery of events for the entire application, not just for a single view.

       一些視圖,比如标簽和圖檔,最初完全禁用事件處理。你可以通過改變視圖的

userInteractionEnabled 屬性值來控制視圖是否允許接收觸摸事件。當一個長事件操作待處理時,你可能臨時設定該屬性為NO來阻止使用者操作視圖的内容。為了阻止事件到達任何一個view,你還可以使用

UIApplication 對象的

beginIgnoringInteractionEvents

  和 

endIgnoringInteractionEvents 方法。 這些方法影響整個app事件的傳遞,不僅僅是影響單個視圖。

Note: The animation methods of

UIView

typically disable touch events while animations are in progress. You can override this behavior by configuring the animation appropriately. For more information about performing animations, see Animations.

      注意:當動畫在進行時,UIView 的動畫方法通常不啟動觸摸事件。你可以通過适當地配置動畫來重寫該行為。 關于執行動畫的更多資訊,請看“Animations.”

--As it handles touch events, UIKit uses the

hitTest:withEvent:

and

pointInside:withEvent:

methods of

UIView

to determine whether a touch event occurred inside a given view’s bounds. Although you rarely need to override these methods, you could do so to implement custom touch behaviors for your view. For example, you could override these methods to prevent subviews from handling touch events.

      當view處理觸摸事件時,UIKit 使用UIView 的 

hitTest:withEvent:

 和 

pointInside:withEvent: 方法來決定一個觸摸事件是否發生在一個給定視圖的邊界内。 盡管很少需要重寫這些方法,但你還是可以在你的自定義視圖裡重寫它們來實作自定義觸摸行為。 比如,你可以重載這些方法來阻止子視圖處理觸摸事件。

Cleaning Up After Your View                                           -- 清理視圖所占的記憶體

If your view class allocates any memory, stores references to any custom objects, or holds resources that must be released when the view is released, you must implement a

dealloc

method. The system calls the

dealloc

method when your view’s retain count reaches zero and it is time to deallocate the view. Your implementation of this method should release any objects or resources held by the view and then call the inherited implementation, as shown in Listing 3-5. You should not use this method to perform any other types of tasks.

        如果你的視圖類配置設定了任何記憶體,存儲了指向任何自定義對象的引用,或保留了一些必須在視圖被釋放之後被釋放的資源, 你必須實作一個dealloc 方法。系統在你的視圖的保留計數值(retain count)變為0時調用dealloc方法,由該方法來釋放視圖。該方法的實作應該釋放由視圖保留的任何對象和資源,然後調用 繼承于dealloc 方法 自身的實作,正如清單3-5所示。 你不應該使用該方法來執行任何其它類型的任務。

Listing 3-5  Implementing the

dealloc

method

- (void)dealloc {

    // Release a retained UIColor object

    [color release];

    // Call the inherited implementation

    [super dealloc];

}