亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

4VisualEffects視覺效果讀書筆記第四章

2019-11-14 18:22:28
字體:
來源:轉載
供稿:網友


4 ? Visual Effects ? ?
視覺效果 ? ? ?? 讀書筆記
第四章

Well, circles and ovals are good, but how about drawing rectangles with rounded corners? Can we do that now, too?

Steve Jobs

?

We looked at the layer frame in Chapter 3, "Layer Geometry," and the layer backing image in Chapter 2, "The Backing Image." But layers are more than mere rectangular containers for colors or images; they also have a number of built-in features that make it possible to create imPRessive and elegant interface elements programmatically. In this chapter, we explore the various visual effects that can be achieved using?CALayer?properties.

我們在這一章將會探索各種不同的視覺效果

Rounded Corners 圓角

One of the signature features of the iOS aesthetic is the use of?rounded rectangles?(rectangles with rounded corners). These appear everywhere in iOS, from homescreen icons, to modal alerts, to text fields. Given their prevalence, you might guess that there would be an easy way to create them without resorting to photoshop. You'd be right.

?

CALayer?has a?cornerRadius?property that controls the curvature of the layer's corners.

CALayer有一個cornerRadius 屬性控制著layercorner的曲線

It is a floating point value that defaults to zero (sharp corners), but can be set to any value you like (specified in points). By default, this curvature affects only the background color of the layer and not the backing image or sublayers.

默認情況下,曲線僅僅是影響layer background color,而不是backing image sublayers.?

However, when the?masksToBounds?property is set to?YES?(see Chapter 2), everything inside the layer is clipped to this curve.

然而,當masksToBounds屬性設置為YES 的時候,任何在這個layer的東西都限制在這里面了。

We can demonstrate this effect with a simple project. Let's arrange a couple of views in Interface Builder that have subviews that extend outside of their bounds (see Figure 4.1). You can't really see from the figure that the inner views extend beyond their containing

views because Interface Builder always clips views in the editing interface. You'll just have to trust that they do.

Figure 4.1?Two large white views, each containing small red views

Using code, we'll apply a 20-point radius to the corners and enable clipping on only the second view (see Listing 4.1). Technically, these properties can both be applied directly in Interface Builder by using User Defined Runtime Attributes and the Clip Subviews checkbox in the Inspector panel, respectively, but in the example this is implemented in code for clarity. Figure 4.2 shows the result.

Listing4.1?ApplyingcornerRadiusandmasksToBounds?@interface?ViewController ()

@property?(nonatomic,?weak)?IBOutlet?UIView?*layerView1;?@property?(nonatomic,?weak)?IBOutlet?UIView?*layerView2;

@end
@implementation
?ViewController

?

- (void)viewDidLoad {

[super?viewDidLoad];

//set the corner radius on our layers

self.layerView1.layer.cornerRadius?=?20.0f;?self.layerView2.layer.cornerRadius?=?20.0f;

//enable clipping on the second layer

self.layerView2.layer.masksToBounds?=?YES; }

@end

It is not possible to control the curvature of each layer corner independently, so if you want to create a layer or view that has some sharp and some rounded corners, you'll need to find a different approach, such as using a?layer mask?(as covered later in the chapter) or?CAShapeLayer?(see Chapter 6, "Specialized Layers").

?

Layer Borders ?邊界

?

Another useful pair of?CALayer?properties are?borderWidth?and?borderColor. Together these define a line that is drawn around the edge of the layer. This line (known as a?stroke) follows the?bounds?of the layer, including the corner curvature.

borderWidth and borderColor 定義了

?

The?borderWidth?is a floating-point number that defines the stroke thickness in points. This defaults to zero (no border). The?borderColor?defines the color of the stroke and defaults to black.

borderWidth 是一個浮點數 定義了繪制點的寬度。默認是0.

?

The type of?borderColor?is?CGColorRef, not?UIColor, so it's not a Cocoa object per-se.

borderColor的類型是CGColorRef,不是UIColor?

However, you should be aware that the layer retains the?borderColor, even though there's no indication of this from the property declaration.?CGColorRef?behaves like an?NSObject?in terms of retain/release, but the Objective-C syntax does not provide a way to indicate this, so even strongly retained?CGColorRef?properties must be declared using?assign.

CGColorRef retain/release NSObject,但是OC語法沒有提供,所以即使retained CGColorRef屬性也必須使用assign修飾。

The border is drawn?inside?the layer bounds, and in front of any other layer contents, including sublayers. If we modify the example to include a layer border (see Listing 4.2), you can see how this works (see Figure 4.3).

Listing 4.2?Applying a Border?@implementation?ViewController

- (void)viewDidLoad {

[super?viewDidLoad];

//set the corner radius on our layers

?

self.layerView1.layer.cornerRadius?=?20.0f;

self.layerView2.layer.cornerRadius?=?20.0f;

//add a border to our layers

?

self.layerView1.layer.borderWidth?=?5.0f;

self.layerView2.layer.borderWidth?=?5.0f;

//enable clipping on the second layer

self.layerView2.layer.masksToBounds?=?YES; }

@end

Figure 4.3?Adding a border around the layer

Note that the layer border does not take the shape of the layer backing image or sublayers into account. If the layer's sublayers overflow its?bounds, or if the backing image has an alpha mask containing transparent areas, the border will still always follow a (possibly rounded) rectangle around the layer (see Figure 4.4).

Figure 4.4?The border follows the?bounds?of the layer, not the shape of its contents.

Drop Shadows 陰影?

?

Another common feature in iOS is the?drop shadow.?Drop shadows are cast behind a view to imply depth. They are used to indicate layering and priority (such as when a modal alert is presented in front of another view), but they are also sometimes used for purely cosmetic purposes (to give controls a more solid appearance).

有時是為了顯示層級,有時就是為了效果了

?

A drop shadow can be shown behind any layer by setting the?shadowOpacity?property to a value greater than zero (the default).

一個drop shadow 可以顯示在任意layer的后面通過設置shadowOpacity屬性給一個比0大的值。

The?shadowOpacity?is a floating-point value and should be set between 0.0 (invisible) and 1.0 (fully opaque).

是浮點數,設置在0.01.0之間。

Setting a value of 1.0 will show a black shadow with a slight blur and a position slightly above the layer. To tweak the appearance of the shadow, you can use a trio of additional?CALayer?properties:?shadowColor,?shadowOffset, and?shadowRadius.

為了設置shadow的外觀,你可以使用三個額外的CALayer 屬性:shadowColor,shadowOffset shadowRadius

?

The?shadowColor?property, as its name implies, controls the shadow color and is a?CGColorRef, just like the?borderColor?and?backgroundColor?properties. The default shadow color is black, which is probably what you want most of the time anyway (colored shadows occur rarely in real life, and can look a bit strange).

shadowColor屬性控制著shadow color 是一個CGColorRef.

?

The?shadowOffset?property controls the direction and distance to which the shadow extends.

shadowOffset屬性控制著陰影的方向和距離

The?shadowOffset?is a?CGSize?value, with the width controlling the shadow's horizontal offset and the height controlling its vertical offset. The default?shadowOffset?is {0, -3}, which results in a shadow positioned 3 points above the layer along the ? ? Y axis. {0,-3}意味著這個shadow position 3 points layer的上面。

?

Why does the default shadow point upward? Although Core Animation was adapted from Layer Kit (the private animation framework created for iOS), its first appearance as a public framework was on Mac OS, which uses an inverted coordinate system with respect to iOS (the Y axis points upward). On a Mac, the same default?shadowOffset?value results in a?downward-pointing shadow, so the default direction makes more sense in that context (see Figure 4.5).

The Apple convention is that user interface shadows point vertically downward, so on iOS it's probably a good idea to use zero for the width and a positive value for the height in most cases.

?

?

The?shadowRadius?property controls the?blurriness?of the shadow. A value of zero creates a hard-edged shadow that exactly matches the shape of the view. A larger value creates a soft-edged shadow that looks more natural. Apple's own app designs tend to use soft shadows, so it's probably a good idea to stick with a nonzero value for this.

一個shadowRadius屬性控制著shadowblurriness .一個0值創建一個硬shadow,恰恰配好view。一個大的值可以創建更自然的軟 邊界的shadow .

Generally, you should use a larger?shadowRadius?for something like a modal overlay than you would to make a control stand out from its background; the blurrier the shadow, the greater the illusion of depth (see Figure 4.6).

?

Figure 4.6?A larger shadow offset and radius increases the illusion of depth.

?

?

Shadow Clipping shadow ?裁剪

?

Unlike the layer border, the layer's shadow derives from the?exact?shape of its contents, not just the?bounds?and?cornerRadius. To calculate the shape of the shadow, Core Animation looks at the backing image (as well as the sublayers, if there are any) and uses these to create a shadow that perfectly matches the shape of the layer (see Figure 4.7).

Figure 4.7?The layer shadow follows the exact outline of the layer backing image.

Layer shadows have an annoying limitation when combined with clipping: Because the shadow is usually drawn outside the layer bounds, if you enable the?masksToBounds?property, the shadow is clipped along with any other content that protrudes outside of the layer. If we add a layer shadow to our border example project, you can see the problem (see Figure 4.8).

Figure4.8?ThemasksToBoundspropertyclipsbothshadowandcontent.

?

This behavior is understandable from a technical perspective, but it is unlikely to be the effect that you wanted. If you want to clip the contents?and?cast a shadow, you need to use two layers: an empty outer layer that just draws the shadow, and an inner one that has?masksToBounds?enabled for clipping content.

如果你想clip content,并cast 一個shadow,你需要用兩層 :一個空的outer layer 僅僅用來繪制shadwo ,和里面的一個有masksToBounds 使得clipping content.

?

If we update our project to use an additional view wrapped around the clipping view on the right, we can solve the problem (see Figure 4.9).

Figure 4.9?An additional shadow-casting view around the clipping view on the right
We attach the shadow only to the outermost view, and enable clipping only on the inner

view. Listing 4.3 shows the updated code, and Figure 4.10 shows the result.

?

Listing 4.3?Using an Additional View to Solve Shadow Clipping Problems

@interface?ViewController ()

?

@property?(nonatomic,?weak)?IBOutlet?UIView?*layerView1;

@property?(nonatomic,?weak)?IBOutlet?UIView?*layerView2;

@property?(nonatomic,?weak)?IBOutlet?UIView?*shadowView;

@end
@implementation
?ViewController

- (void)viewDidLoad {

[super?viewDidLoad];

//set the corner radius on our layers

?

self.layerView1.layer.cornerRadius?=?20.0f;

self.layerView2.layer.cornerRadius?=?20.0f;

//add a border to our layers

?

self.layerView1.layer.borderWidth?=?5.0f;

self.layerView2.layer.borderWidth?=?5.0f;

//add a shadow to layerView1

?

self.layerView1.layer.shadowOpacity?=?0.5f;

self.layerView1.layer.shadowOffset?=?CGSizeMake(0.0f,?5.0f);?self.layerView1.layer.shadowRadius?=?5.0f;

//add same shadow to shadowView (not layerView2)

?

self.shadowView.layer.shadowOpacity?=?0.5f;

self.shadowView.layer.shadowOffset?=?CGSizeMake(0.0f,?5.0f);?self.shadowView.layer.shadowRadius?=?5.0f;

//enable clipping on the second layer

self.layerView2.layer.masksToBounds?=?YES; }

@end

?

Figure 4.10?The view on the right now has a shadow, despite clipping.

The?shadowPath?Property

We've established that layer shadows are not always square, but instead derive from the shape of the contents. This looks great, but it's also very expensive to calculate in real time, especially if the layer contains multiple sublayers, each with alpha-masked backing images.

?

If you know in advance what the shape of your shadow needs to be, you can improve performance considerably by specifying a?shadowPath. The?shadowPath?is a?CGPathRef?(a pointer to a?CGPath?object).

shadowPath是一個CGPathRef對象

CGPath?is a Core Graphics object used to specify an arbitrary vector shape. We can use this to define the shape of our shadow independently of the layer's shape.

我們可以定義我們的shadow的形狀獨立于layer的形狀

Figure 4.11 shows two different shadow shapes applied to the same layer image. In this case, the shapes we've used are simple, but they can be absolutely any shape you want. See Listing 4.4 for the code.

Figure4.11?UsingshadowPathtocastshadowswitharbitraryshapes

?

Listing 4.4?Creating Simple Shadow Paths

@interface?ViewController ()

?

@property?(nonatomic,?weak)?IBOutlet?UIView?*layerView1;

@property?(nonatomic,?weak)?IBOutlet?UIView?*layerView2;

@end
@implementation
?ViewController

- (void)viewDidLoad {

[super?viewDidLoad];

//enable layer shadows

self.layerView1.layer.shadowOpacity?=?0.5f;

self.layerView2.layer.shadowOpacity?=?0.5f;

//create a square shadow

CGMutablePathRef?squarePath =?CGPathCreateMutable();

CGPathAddRect(squarePath,?NULL,?self.layerView1.bounds);

self.layerView1.layer.shadowPath?= squarePath;

CGPathRelease(squarePath);

//create a circular shadow

CGMutablePathRef??circlePath =?CGPathCreateMutable();

CGPathAddEllipseInRect(circlePath,?NULL,?self.layerView2.bounds);?self.layerView2.layer.shadowPath?= circlePath;

CGPathRelease(circlePath);

}

@end

For something like a rectangle or circle, creating a?CGPath?manually is fairly straight- forward. For a more complex shape like a rounded rectangle, you'll probably find it easier to use the?UIBezierPath?class, which is an Objective-C wrapper around?CGPath?provided by UIKit.

Layer Masking?

Using the?masksToBounds?property, we know that it is possible to clip a layer's contents to its?bounds, and using the?cornerRadius?property, we can even give it rounded corners. But sometimes you will want to represent content that is not rectangular or even rounded-rectangular in shape. For example, you might want to create a star-shaped photo frame around an image, or you might want the edges of some scrolling text to fade gracefully into the background instead of clipping to a sharp edge.

Using a 32-bit PNG image with an alpha component, you can specify a backing image that includes an arbitrary alpha mask, which is usually the simplest way to create a non- rectangular view. But that approach doesn't allow you to clip images dynamically using programmatically generated masks or to have sublayers or subviews that also clip to the same arbitrary shape.

?

CALayer?has a property called?mask?that can help with this problem. The?mask?property is itself a?CALayer?and has all the same drawing and layout properties of any other layer.

mask 屬性自己也是個CALayer,有所有相同的drawing layout屬性 ?

It is used in a similar way to a sublayer in that it is positioned relative to its parent (the layer that owns it), but it does not?appear?as a normal sublayer. Instead of being drawn inside the parent, the?mask?layer defines the part of the parent layer that is visible.

不是drawnparent的里面,mask layer 定義了可以看見的父layer的一部分。

?

The?color?of the?mask?layer is irrelevant; all that matters is its?silhouette.

mask layercolor無關緊要,重要的是他的silhouette

The?mask?acts like a cookie cutter; the solid part of the?mask?layer will be "cut out" of its parent layer and kept; anything else is discarded (see Figure 4.12).

?

If the?mask?layer is smaller than the parent layer, only the parts of the parent (or its sub- layers) that intersect the?mask?will be visible. If you are using a?mask?layer, anything outside of that layer is implicitly hidden.

如果mask layer parent layer 小,僅僅與mask有交集的parent 才可見。

?

Figure 4.12?Combining separate image and mask layers to create a masked image

To demonstrate this, let's create a simple project that masks one image with another using the layer?mask?property. To simplify things, we'll create our image layer in Interface Builder using a?UIImageView, so that only the?mask?layer needs to be created and applied programmatically. Listing 4.5 shows the code to do this, and Figure 4.13 shows the result.

?

Listing 4.5?Applying a Layer Mask

@interface?ViewController ()

?

@property?(nonatomic,?weak)?IBOutlet?UIImageView?*imageView;

@end

@implementation?ViewController

- (void)viewDidLoad {

[super?viewDidLoad];

//create mask layer

?

CALayer?*maskLayer = [CALayer?layer];
maskLayer.frame
?=?self.layerView.bounds;

UIImage?*maskImage = [UIImage?imageNamed:@"Cone.png"];

maskLayer.contents?= (__bridge id)maskImage.CGImage;

//apply mask to image layer

self.imageView.layer.mask?= maskLayer;

}

?

@end

Figure4.13?Our ?UIImageView,after the?mask?layer has been applied

The?really?cool feature of?CALayer?masking is that you are not limited to using static images for your masks. Anything that can be composed out of layers can be used as the?mask?property, which means that your masks can be created dynamically using code, and even animated in real time.

?

Scaling Filters ?縮放過濾

?

The final topic we cover in this chapter is the effect of the?minificationFilter?and?magnificationFilter?properties.

縮小過濾 和放大過濾屬性?

Generally on iOS, when you display images, you should try to display them at the correct size (that is, with a 1:1 correlation between the pixels in the image and the pixels onscreen). The reasons for this are as follows:

?

??It provides the best possible quality, because the pixels aren't stretched or resampled.

??It makes the best use of RAM, because you aren't storing more pixels than needed.

??It yields the best performance, because the GPU doesn't have to work as hard.

Sometimes, however, it's necessary to display an image at a larger-than-actual or smaller- than-actual size. Examples might include a thumbnail image of a person or avatar, or a very large image that the user can pan and zoom. In these cases, it might not be practical to store separate copies of the image for every size it might need to be displayed at.

?

When images are displayed at different sizes, an algorithm (known as a?scaling filter) is applied to the pixels of the original image to generate the new pixels that will be displayed onscreen.

當一個圖片展示不同的尺寸,一個算法 scaling filter 應用到了原始圖片的像素來展示一個新的pixel?

?

There is no universally ideal algorithm for resizing an image. The approach depends on the nature of the content being scaled, and whether you are scaling up or down.?CALayer?offers a choice of three scaling filters to use when resizing images. These are represented by the following string constants: 提供了三個縮放filters 來調整圖片

kCAFilterLinear kCAFilterNearest kCAFilterTrilinear

The default filter for both?minification?(shrinking an image) and?magnification?(expanding an image) is?kCAFilterLinear. This filter uses the?bilinear?filtering algorithm, which yields good results under the majority of circumstances. Bilinear filtering works by sampling multiple pixels to create the final value. This results in nice, smooth scaling, but can make the image appear blurry if it scaled up by a large factor (see Figure 4.14).

The?kCAFilterTrilinear?option is very similar to?kCAFilterLinear. There is no visible difference between them in most cases, but?trilinear?filtering improves on the performance of bilinear filtering by storing the image at multiple sizes (known as?mip- mapping) and then sampling in three dimensions, combining pixels from the larger and smaller stored image representations to create the final result.

The advantage of this approach is that the algorithm can work from a pair of images that are already quite close to the final size. This means that it does not need to sample as many pixels simultaneously, which improves performance and avoids the sampling glitches that can occur at very small scale factors due to rounding errors.

Figure 4.14?For larger images, bilinear or trilinear filtering is usually better.

?

The?kCAFilterNearest?option is the crudest approach. As the name suggests, this algorithm (known as?nearest-neighbor?filtering) just samples the nearest single pixel and performs no color blending at all. This is very fast, and doesn't blur the image, but the quality is noticeably worse for shrunken images, and magnified images become blocky and pixelated.

?

In Figure 4.14, note how the bilinear image looks less distorted than the nearest-neighbor version when shrunk to a small size, but when enlarged it looks blurrier. Contrast this with Figure 4.15, where we've started with a very small image. In this instance, nearest-neighbor does a better job of preserving the original pixels, whereas linear filtering turns them into a blurry mess regardless of whether the image is minified or magnified.

Figure 4.15?For small images without diagonals, nearest-neighbor filtering is better.

Generally speaking, for very small images or larger images with sharp contrast and few diagonal lines (for example, computer-generated images), nearest-neighbor scaling will preserve contrast and may yield better results. But for most images, especially photographs or images with diagonals or curves, nearest-neighbor will look appreciably worse than linear filtering. To put it another way, linear filtering preserves the?shape, and nearest- neighbor filtering preserves the?pixels.

Let's try a real-world example. We'll modify the clock project from Chapter 3 to display an LCD-style digital readout instead of an analog clock face. The digits will be created using a simple?pixel font?(a font where the characters are constructed from individual pixels rather than vector shapes), stored as a single image and displayed using the sprite sheet technique introduced in Chapter 2 (see Figure 4.16).

Figure 4.16?A simple "pixel font" sprite sheet for displaying LCD-style digits

We'll arrange six views in Interface Builder, two each for the hours, minutes, and seconds digits. Figure 4.17 shows how the views are arranged in Interface Builder. That many views starts to get a bit unwieldy when using individual outlets, so we'll connect them to the controller using an?IBOutletCollection, which allows us to access the views as an array. Listing 4.6 shows the code for the clock.

Figure 4.17?The clock digit views arranged into hours, minutes, and seconds

?

Listing 4.6?Displaying an LCD-Style Clock

@interface?ViewController ()

@property?(nonatomic, strong)?IBOutletCollection(UIView)?NSArray?*digitViews;?@property?(nonatomic,?weak)?NSTimer?*timer;

?

@end
@implementation
?ViewController

- (void)viewDidLoad {

[super?viewDidLoad];?//get spritesheet image

UIImage?*digits = [UIImage?imageNamed:@"Digits.png"];

//set up digit views

for?(UIView?*view?in self.digitViews) {

//set contents

view.layer.contents?= (__bridge id)digits.CGImage; view.layer.contentsRect?=?CGRectMake(0,?0,?0.1,?1.0); view.layer.contentsGravity?=?kCAGravityResizeaspect;

}

//start timer

self.timer = [NSTimer?scheduledTimerWithTimeInterval:1.0?target:self

//set initial clock time

[self?tick]; }

  • -   (void)setDigit:(NSInteger)digit forView:(UIView?*)view {

    //adjust contentsRect to select correct digit

    view.layer.contentsRect?=?CGRectMake(digit *?0.1,?0,?0.1,?1.0); }

  • -   (void)tick {

    //convert time to hours, minutes and seconds

    NSCalendar?*calendar = [[NSCalendar?alloc]?initWithCalendarIdentifier:?NSGregorianCalendar];

    NSUInteger?units =?NSHourCalendarUnit?|?NSMinuteCalendarUnit?|

    NSSecondCalendarUnit;

selector:@selector(tick)?userInfo:nil

repeats:YES];

NSDateComponents?*components = [calendar?components:units?fromDate:[NSDate?date]];

//set hours

[self?setDigit:components.hour?/?10?forView:self.digitViews[0]]; [self?setDigit:components.hour?%?10?forView:self.digitViews[1]];

//set minutes

[self?setDigit:components.minute?/?10?forView:self.digitViews[2]]; [self?setDigit:components.minute?%?10?forView:self.digitViews[3]];

//set seconds

[self?setDigit:components.second?/?10?forView:self.digitViews[4]];

[self?setDigit:components.second?%?10?forView:self.digitViews[5]]; }

@end

?

As you can see from Figure 4.18, it works, but the digits look blurry. It seems that the default?kCAFilterLinear?option has failed us.

?

?

To get the crisp digits shown in Figure 4.19, we just need to add the following line to the

?

for...in?loop in our program:?view.layer.magnificationFilter?=?kCAFilterNearest;

?

Group Opacity 組合透明度

?

UIView?has a handy?alpha?property that can be used to vary its transparency.?CALayer?has an equivalent property called?opacity. Both properties work hierarchically, so if you set the?opacity?of a layer it will automatically affect all of its sublayers, as well.

UIView有一個alpha 屬性可以用來改變它的透明度。CALayer也有一個相等的屬性叫做opacity.兩個屬性都工作在層級上。

?

A common trick in iOS is to set a control's?alpha?to 0.5 (50%) to make it appear disabled.

一個常用的技巧是設置iOSalpha 0.5 來使它顯示失效。

This works great for individual views, but when a control has subviews it can look a bit strange. Figure 4.20 shows a custom?UIButton?containing a nested?UILabel; on the left is an opaque button, and on the right is the same button shown with 50% alpha. Notice how we can see the outline of the internal label against the button background.

?

Figure 4.20?In the faded button on the right, the internal label's border is clearly visible.

This effect is due the way that alpha blending works. 混合的結果 ?When you display a layer with 50% opacity, each pixel of the layer displays 50% of its own color and 50% of the layer behind it. That results in the appearance of translucency. But if the layer contains sublayers that are also displayed at 50% transparency, then when you look through the sublayer, you are seeing 50% of the sublayer's color, 25% of the containing layer's color, and only 25% of the background color.

In our example, the button and label both have white backgrounds. Even though they are both only 50% opaque, their combined opacity is 75%, and so the area where the label overlaps the button look less transparent than the surrounding part. This serves to highlight all of the sublayers that make up a control and produces a nasty visual effect.

?

Ideally, when you set the?opacity?of a layer, you want its entire subtree to fade as if it were a single layer, without revealing its internal structure.

理想情況下,當你設置一個layeropacity的時候,你想讓你的整個subtree fade 成為一個簡單的layer,沒必要revealing 他的內部結構。?

You can achieve this by setting?UIViewGroupOpacity?to?YES?in your?Info.plist?file, but this affects the way that blending is handled across the whole application, and introduces a small app-wide performance penalty. If the?UIViewGroupOpacity?key is omitted, its value defaults to?NO?on iOS 6 and earlier (though the default may change in a future iOS release).

?

Alternatively, you can implement group opacity for a specific layer subtree by using a?CALayer?property called?shouldRasterize?(see Listing 4.7).

你可以實現groupt opacity 給一個特定的layer subtree 通過使用CALayer 的稱為shouldRasterreize的屬性

When set to?YES, the?shouldRasterize?property causes the layer and its sublayers to be collapsed into a single flat image?before the opacity is applied, thereby eliminating the blending glitch (see Figure 4.21).

In addition to enabling the?shouldRasterize?property, we've modified the layer's?rasterizationScale?property. By default, all layers are rasterized at a scale of 1.0, so if you use the?shouldRasterize?property, you should always ensure that you set the

rasterizationScale?to match the screen to avoid views that look pixelated on a Retina display.

As with?UIViewGroupOpacity, use of the?shouldRasterize?property has performance implications (which are explained in Chapter 12, "Tuning for Speed," and Chapter 15, "Layer Performance"), but the performance impact is localized.

Listing 4.7?Using?shouldRasterize?to Fix the Grouped Blending Problem?@interface?ViewController ()

@property?(nonatomic,?weak)?IBOutlet?UIView?*containerView;?@end
@implementation
?ViewController

  • - (UIButton?*)customButton {
    //create button
    CGRect?frame =?CGRectMake(0,?0,?150,?50);
    UIButton
    ?*button = [[UIButton?alloc]?initWithFrame:frame];
  • button.backgroundColor?= [UIColor?whiteColor];
  • button.layer.cornerRadius?=?10;//add label
  • frame =?CGRectMake(20,?10,?110,?30);
    UILabel
    ?*label = [[UILabel?alloc]?initWithFrame:frame];
  • label.text?=?@"Hello World";
    label.textAlignment
    ?=?NSTextAlignmentCenter;
    [button
    ?addSubview:label];
  • return?button;
  • }
  • - (void)viewDidLoad {

    [super?viewDidLoad];

    //create opaque button

    UIButton?*button1 = [self?customButton];

  • button1.center?=?CGPointMake(50,?150);
  • [self.containerView?addSubview:button1];

    //create translucent button

    UIButton?*button2 = [self?customButton];

? ?button2.center?=?CGPointMake(250,?150);

? ?button2.alpha?=?0.5;

? ?[self.containerView?addSubview:button2];

//enable rasterization for the translucent button

button2.layer.shouldRasterize?=?YES;

button2.layer.rasterizationScale?= [UIScreen?mainScreen].scale;

}

?

@end

?

Summary

This chapter explored some of the visual effects that you can apply programmatically to layers, such as rounded corners, drop shadows, and masks. We also looked at scaling filters and group opacity.

?

In Chapter 5, "Transforms," we investigate layer transforms and transport our layers into the third dimension.


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美电影免费观看高清完整| 日韩中文字幕在线视频播放| 亚洲成人免费在线视频| 日韩美女视频免费看| 日韩精品中文字幕久久臀| 在线视频欧美日韩| 欧美激情成人在线视频| 国产91精品在线播放| 91九色国产视频| 91精品国产沙发| 欧美日韩加勒比精品一区| 中文在线资源观看视频网站免费不卡| 国产区亚洲区欧美区| 性欧美在线看片a免费观看| 久久精品视频导航| 国产精品免费看久久久香蕉| 亚洲qvod图片区电影| 91精品国产91| 黑人狂躁日本妞一区二区三区| 在线电影av不卡网址| 国产日本欧美一区二区三区| 国产一区私人高清影院| 狠狠色香婷婷久久亚洲精品| 中文字幕亚洲情99在线| 色综合久综合久久综合久鬼88| 色狠狠久久aa北条麻妃| 精品偷拍一区二区三区在线看| 一区二区三区国产视频| 欧美午夜美女看片| 国产成人精品久久二区二区| 亚洲精品在线91| 欧美电影免费播放| 亚洲图中文字幕| 97久久超碰福利国产精品…| 亚洲欧洲xxxx| 成人精品视频在线| 国产欧美精品日韩| 久久精视频免费在线久久完整在线看| 亚洲视频999| 久久久精品免费| 91免费精品视频| 日韩中文字幕在线观看| 91av成人在线| 91av在线免费观看| 一夜七次郎国产精品亚洲| 日韩av免费在线播放| 欧美日本高清视频| 日韩美女免费视频| 久久好看免费视频| 欧美另类在线播放| 亚洲bt天天射| 国产精品久久久久久久天堂| 久青草国产97香蕉在线视频| 精品中文字幕在线观看| 国外日韩电影在线观看| 国产精品网站视频| 国产精品尤物福利片在线观看| 91久久久久久久久久久| 欧美成人免费在线视频| 91探花福利精品国产自产在线| 国产成人精品电影久久久| 91在线无精精品一区二区| 精品国产91久久久久久老师| 欧美在线视频在线播放完整版免费观看| 欧美成人精品在线观看| 中文字幕亚洲欧美一区二区三区| 亚洲国产精品va在线| 国产日韩欧美自拍| 日韩av电影院| 国产一区在线播放| 亚洲国产天堂久久综合| 中文字幕欧美专区| 国产精品激情av在线播放| 日产精品久久久一区二区福利| 久久在精品线影院精品国产| 欧美激情第1页| 亚洲精品女av网站| 色综合天天狠天天透天天伊人| 国产精品一区二区电影| 伊人久久大香线蕉av一区二区| 自拍偷拍亚洲在线| 亚洲天堂久久av| 97国产精品视频人人做人人爱| 国外成人在线直播| 国产精品极品美女粉嫩高清在线| 国产精品丝袜视频| 国产精品视频久久久| 欧美日韩免费在线观看| 亚洲第一网站男人都懂| 欧美午夜激情小视频| 欧美激情伊人电影| 欧美成人午夜剧场免费观看| 国产精品高清网站| 久久久久久这里只有精品| 国产日韩欧美日韩| 久久伊人精品视频| 欧美一级视频在线观看| 亚洲欧美国产精品| 日本国产高清不卡| 国产精品主播视频| 欧美日韩中文字幕综合视频| 亚洲第一av网站| 在线视频日韩精品| 2019中文在线观看| 国产成人精品久久二区二区| 国产精品高清免费在线观看| 亚洲乱码一区av黑人高潮| 亚洲2020天天堂在线观看| 91精品中国老女人| 91久久久久久久久久久| 日韩精品在线观看网站| 欧美巨猛xxxx猛交黑人97人| 欧美日韩999| 欧美肥老妇视频| 日本不卡视频在线播放| 国产成人久久精品| 亚洲欧美制服丝袜| 欧美成人精品激情在线观看| 日韩av网址在线| 亚洲欧美精品一区二区| 亚洲欧美在线播放| 国产精品久久久久久五月尺| 中文字幕亚洲二区| 久久免费精品日本久久中文字幕| 午夜欧美大片免费观看| 精品调教chinesegay| 欧美激情第1页| 日韩欧美国产激情| 日韩在线不卡视频| 亚洲免费电影在线观看| 91成人福利在线| 欧美成人黑人xx视频免费观看| 97精品视频在线播放| 国产精品第10页| 亚洲国产欧美精品| 精品国产一区二区三区在线观看| 色妞一区二区三区| 国产suv精品一区二区| 久久久久久国产免费| 97久久精品人人澡人人爽缅北| 国产精品7m视频| 综合国产在线观看| 国产精品一区二区久久久| 91视频8mav| 国产美女被下药99| 色偷偷噜噜噜亚洲男人| 韩曰欧美视频免费观看| 国产精品视频免费在线| 琪琪亚洲精品午夜在线| 国产一区二区在线播放| 国内精品一区二区三区四区| 久久久综合免费视频| 亚洲人成77777在线观看网| 精品中文字幕在线| 亚洲免费人成在线视频观看| 国产精品自产拍在线观看中文| 欧洲午夜精品久久久| 日韩电影中文字幕| 亚洲毛茸茸少妇高潮呻吟| 欧美精品在线极品| 久久视频在线免费观看| 欧美极品在线播放| 亚洲视频第一页| 国产69精品久久久久久|