`
shfzhzhr
  • 浏览: 70578 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Views vs. Layers

    博客分类:
  • IOS
 
阅读更多

 

 

For many iOS developers, layers are a lower-level, complex version of the UIView. In reality, it’s the UIView which is a thin layer on top of CALayer. Unfortuntely, 95% of the iOS books and documentation out there talk almost exclusively about the UIKit and so it’s no surprise we get that impression.

In this blog, I’m going to explain the difference between UIView and CALayer, tell you when you should be using either, and demonstrate the power of layers by creating a working clock.

UIView vs. CALayer

Despite what many developers think, it’s the CALayer that’s the fundamental drawing unit in iOS. The reason why we perceive UIView as such is because it’s a thin layer on top of CALayer and for most UI challenges using some form of UIView works just fine. You can create custom views, draw into them, handle user interactions, and even animate them without ever having to touch CALayer.

Every UIView comes packaged with a CALayer knows as the “backing layer” or “underlying layer.” Many of the methods you call on UIView simply delegate to the layer. When you change a view’s frame, it’s simply changing the layer’s frame. If you change the alpha, it changes the layer’s alpha…and so on with background colors, transformations and more. And while you can maintain a hierarchy of UIViews each representing parents and children of one another, you can do the same with CALayer.

Now, let’s say you wanted to write a Bar Chart component. You’d subclass UIView (or better yet, UIControl) and write the logic for displaying the colored bars you need to represent your data. If you’re comfortable with the UIKit, you might find it an easy choice to use subviews to represent each bar. You can use a plain UIView, slap a background color on it, size it…and repeat a dozen times depending on how much data you’re representing. But, you’d be wrong. You shouldn’t be using subviews, you should be using sublayers.

Should I use subviews or sublayers?

This isn’t a simple question, but there’s one rule of thumb that make deciding a lot easier. The main different between a view and a layer is that views can accept user input while a layer cannot. A layer is simply a graphical representation. Views can handle user taps, drags, pinches, etc. To me, this is all you need to know.

So, when making your bar chart, you should be using sublayers for the bars. Why? Because they don’t need user input and since they’re lighter weight than views, they’re the right choice. So what do you gain by using layers? Well, aside from performance, you also gain implicit animation and better control of the visual representation. You see, every property you change on a layer is automatically animated. You can disable them if you need to, but they come in handy. Also, you can apply shadow effects, corner radiuses, 3D transforms and more on layers. You can apply many of these on views, too, but they’re simply delegating to their “underlying layer” and in many cases stealing event notifications you’d rather they not from your view. :-)

Demo: Let’s build a working clock!

To demonstrate how we use layers, I’m going to build a working clock. The architecture will be as follows:

 

  • ClockView will extend UIControl so that we can use it with Interface Builder and, potentially in the future, handle user events.
  • All the parts of the clock will be layers.
  • Since all of the parts are layers, we won’t be implementing drawRect.
  • A timer, that we can start and stop, will handle updating the clock by adjusting the three hands.

 



Here’s what our clock looks like:

 

 


Every piece of it is rendered in layers: the face, numbers, ticks, all three hands, and the centerpoint. I used a mix of techniques to render it. Shadow effects give the hands depth, rounded line miters give the hands softness, and combining anchoring with transforms gives the hands a more natural clock look by having them rotate around the centerpoint. No PNGs were used and no primitives were drawn.

Here’s the source code. You can take this code and drop it right into your own project. Simply call ClockView#startUpdates to get things going! Also, note that I only implement initWithCoder, so if you want to add it to your UI programmatically, override initWithFrame as well. You’ll also need to link in the QuartzCore framework — anything that uses CA* will need it.

(NOTE: It’s not a memory leak, it’s ARC! Also, I recommend using constants instead of raw time constants. Why not try iBoost?)

On line #41, I use a CAShapeLayer. These things are awesome! By providing a path, you can make a layer of any shape. You can specify stroke and fill colors, change line attributes, and so on. The clock would be way more complex without these bad boys.

On line #45, I use the position property to place the face layer. Layers are positioned differently than views. While you might use frame, bounds, or center to position a view…you use bounds, position, and anchorPoint to position a layer. While bounds works as expected, position and anchorPoint are different. The anchorPoint is a CGPoint where the X and Y normally range between 0 and 1. The 0 represents the top or left of the image, and 1 is the bottom or right of the image. The default is 0.5, 0.5 which is the center of the image. That means that whatever you set the position property to, that’s where the center of the layer will be. You can change the anchorPoint to position things differently. If you set it to 0, 0, position will be where the top left of the image is. Get it? Additionally, you can make an anchor 0.5, 10 which will position the layer 10X the height of the layer above the position. Magic.

On line #59, I use a CATextLayer which lets you specify text easily as a layer.

On line #67, I use 3D transforms to position the numbers. By making the bounds of the number higher than expected, a simple rotational transform positions the numbers where I want. (If you wanted the numbers all “face up”, you’d have to position these using trigonometry instead, but this is a layer demo!) Note that the last 3 params of this method specify which axes to rotate around. I specify the last one, which is the z-axis, which is by far the most common.

Summary

Layers are the powerful core of the Cocoa Touch framework. Even if you’ve never used a layer directly, you’re probably familiar with many concepts because UIViews are simply thin layers on top of them. Want to give your view a rounded rectangle appearance? Simply set myView.layer.cornerRadius to 5.0! Want dynamic drop shadows to make image sizing easier? Set myView.layer.shadowOpacity greater than 0.0. DONE! Remember, UIViews are designed to handle user input, and layers are the graphical workhorse. Use them!

分享到:
评论

相关推荐

    iOS 4 编程(英文版)

    16. Layers 17. Animation 18. Touches 19. View Controllers 20. Scroll Views 21. Table Views 22. Popovers and Split Views 23. Text 24. Web Views 25. Controls and Other Views 26. Modal Dialogs 27. Audio ...

    PyPI 官网下载 | django_layers-0.7.2.tar.gz

    5. **src**或**django_layers**目录:包含实际的源代码,可能有models、views、urls、templates等子目录,对应Django应用的不同组件。 6. **tests**目录:用于存放单元测试和集成测试,确保代码的质量和稳定性。 7...

    ArcGIS API for JavaScript4.10 sdk and api

    3. 加载图层:使用 `esri.layers.MapImageLayer` 或 `esri.layers.FeatureLayer` 加载地图服务或矢量数据。 4. 图层控制:利用 `layer.setVisible()` 和 `layer.setOpacity()` 控制图层的可见性和透明度。 5. 查询...

    ArcGIS API for JavaScript 4.5 API

    - **服务接入**:通过`esri.layers.FeatureLayer`、`esri.layers.TileLayer`等加载不同类型的GIS服务。 - **图层操作**:使用`layer.setVisible()`、`layer.setOpacity()`等方法控制图层的可见性和透明度。 - **...

    Android代码-view-effects

    At the beginning the only purpose was to blur all layers below. Now you can do more : Blur background views easily Create custom filters and apply them to views backgrounds Screenshot Usage First ...

    arcgis js api4.x 调用高德影像扩展类和示例

    var gaoDeLayer = new esri.layers.WebTileLayer({ urlTemplate: "http://wprd{0}.iserver.cn/map-world/v2.1/rest/services/World/ImageServer/{z}/{y}/{x}.jpg", subDomains: ["0", "1", "2", "3"], layerInfo...

    利用ArcGis API解析FileGDB

    var layer = view.map.layers.getItemAt(0); console.log(layer.fields.map(field => field.name)); }); }); ``` **5. 扩展应用** 除了基本的读取和查询,ArcGIS API还可以用来执行更多高级操作,如空间分析...

    Programming Excel With Vba And .net.chm

    CustomView and CustomViews Members Section 11.10. HPageBreak, HPageBreaks, VPageBreak, VPageBreaks Members Section 11.11. PageSetup Members Section 11.12. Graphic Members Section 11.13. ...

    Android.Games.Practical.Programming.By.Example.Quickstart

    You'll be able to implement the activity's lifecycle callback methods and utilize handlers to switch views in game. This unit also goes into detail on how to write the main thread and view for your ...

    arcgis api 4.x for js 全球流动图.zip

    1. 时间动态:ArcGIS API 4.x支持时间感知,可以通过`esri/layers/TimeInfo`设置数据的时间范围和间隔,结合`esri/views/time`管理时间滑块,实现数据随时间变化的动态流动图。 2. 图层叠加:通过添加多个图层,...

    ArcGIS API for js4.15加载高德地图作为底图

    var gaodeMap = new esri.layers.TileLayer({ url: ...

    完整的arcgis for js调用天地图示例

    map.layers.raiseToTop(tmsLayer); ``` 5. 添加事件监听:可以添加事件监听器来响应用户的交互,例如点击地图、缩放等。 ```javascript view.on("click", function(event) { console.log("点击位置:", event....

    arcgis-js-v429-sdk api

    3. Layers:Layers是地图上的基本元素,可以是矢量图层、栅格图层、地形图层等,它们承载了地理数据并决定地图的显示方式。 4. Geocoding:地理编码是将地址转换为坐标的过程,API提供了这个功能,便于在地图上定位...

    arcgis api 3.x for js 入门开发系列八聚合效果源码

    ArcGIS API 3.x提供了`esri/views/2d/layers/FeatureLayerView2D`类的`clusterOptions`属性来实现聚合功能。我们可以通过设置`clusterRadius`参数定义聚集体的半径,`clusterMinSize`和`clusterMaxSize`来控制聚集体...

    Odoo 11 Development Essentials 3 Edition(epub)

    While the example is kept simple, it covers all the different layers and components that can be involved in an Odoo application: models, business logic, backend views, and web frontend views. ...

    arcgis_js_v322_sdk.zip

    `esri.layers`模块则包含了各种类型的图层,如TiledMapServiceLayer、DynamicMapServiceLayer等,可以显示不同数据源的地图服务。 在API 3.22版本中,有一些重要的更新和改进。其中,增强了对3D地图的支持,使得...

    arcgis api for js 加载webMercator天地图.rar

    require(["esri/Map", "esri/views/MapView", "esri/layers/TiledMapServiceLayer"], function(Map, MapView, TiledMapServiceLayer) { // ... }); ``` 2. 创建地图和视图 接着,使用`esri/Map`创建一个地图...

    arcgis for javascript

    1. **地图加载**:使用`esri/Map`和`esri/views/MapView`类创建地图和视图,指定本地地图资源。 2. **图层层级控制**:通过`Map.layers`和`MapView.ui`进行图层添加、移除及显示顺序调整。 3. **交互式功能**:...

Global site tag (gtag.js) - Google Analytics