dimensionpage layout 意思是什么意思

使用Autolayout实现UITableView的Cell动态布局和高度动态改变
本文翻译自:有人在上问了一个问题:如何在UITableViewCell中使用Autolayout来实现Cell的内容和子视图自动计算行高,并且能够保持平滑滚动的?这个问题得到了300+的支持和450+的收藏,答案得到了730+的支持,很详细的说明了如何在iOS7和iOS8上实现UITableView的动态行高功能,并且这个答案对实现UICollectionView的动态行高也具有参考意义。所以在这里将这个答案翻译了一下,希望对大家有所帮助。以下是答案的全文翻译:答案略长,如果你不喜欢细读,可以直接看这两个示例的代码:
- iOS8以上才支持
- iOS7+核心概念不管你是在哪个iOS版本上做开发,以下步骤中的前两个步骤都是必须的:1、设置好布局约束条件在UITableViewCell子类中,添加布局约束,使得cell子视图的边缘固定(pin)到cell的contentView的边缘(最重要的是要有顶部和底部的边距约束条件)。注意:不要将子视图的边距约束固定到cell本身上了,只能固定到cell的contentView上! 确保每个子视图垂直方向上的内容压缩阻力(compression resistance)和吸附性约束(hugging constraints)没有被你添加的更高优先级的约束条件覆盖,让这些子视图的固有内容尺寸(intrinsic content size)来驱动contentView的高度。()记住,要点是让cell的子视图与contentView之间产生垂直的连结,让它们能够对contentView“施加压力”,使contentView扩展以适合它们的尺寸。下面用一个cell和一些子视图作为示例,展示了你的一些(不是全部!)布局约束应该看起来是什么样的:可以设想,随着更多的文本被添加到上例中“Multi-line body”那个label上,它需要垂直地增高以适合文本,这将有效地迫使cell的高度增加。(当然,你需要正确地设置约束条件,以使其正常的工作!)如何设置正确的约束条件,绝对是使用Autolayout实现动态行高时最难最重要的部分。如果弄错了,它就可能无法正常工作——所以,不要着急,慢慢来!我建议你用代码来设置布局约束,这样你就完全知道每个布局约束被加到了什么地方,出问题时也更容易调试。特别如果使用一些优秀开源库,可以让用代码设置约束和用Interface Builder设置约束一样简单直观,并且功能还更强大。这里也有一个由我设计和维护的专用库:
● 如果你用代码来设置布局约束,你应该在UITableViewCell子类的updateConstraints方法里面一次性完成。注意,updateConstraints可能不止被调用一次,因此要避免重复添加相同的布局约束。在updateConstraints中,可以将添加布局约束的代码包在一个if条件语句中(比如用一个叫didSetupConstraints的布尔属性,运行一次添加布局约束的代码后就将其设置为YES),以确保不重复添加相同的布局约束。另外,更新已有布局约束的代码(比如调整布局约束的constant属性),也应该将它们放置在updateConstraints 中,但是要在didSetupConstraints条件语句的外面,这样才可以确保每次调用的时候都会被执行。2. Cell使用具有唯一性的重用标示符在cell里面,为每一组特定的约束条件,使用一个特定的cell重用标示符。换句话说,如果cell有多种不同的布局,每一种布局应当有其对应的重用标示符。(当cell有多种不同数量的子视图的时候,或者子视图以一种独特的方式布局的时候,这些情况下你就需要使用一个新的重用标示符。)例如,要在一个cell中显示一条email消息,可能会有4种独特的布局:第一种,只有主题的消息;第二种,带主题和正文的消息;第三种,带主题和图片附件的消息;第四种,带主题、正文和图片附件的消息。每一种布局都需要完全不同的布局约束才能实现。因此,一旦cell被初始化并且布局约束被加到其中任意一种类型的cell上后,cell应当得到一个唯一的重用标示符来指定该cell类型。这就意味着,当你dequeue重用一个cell的时候,该类型cell的布局约束已经添加好了,可以直接使用。注意,由于固有内容尺寸的不同,具有相同布局约束的cell仍然可能具有不同的高度!不要混淆了布局(不同的约束)和由不同内容尺寸而计算出(通过相同的布局约束来计算)的不同视图frame这两个概念,它们根本是完全不同的两个东西。
● 不要将拥有不同布局约束条件的cell丢到同一个重用池当中(也就是使用相同的重用标示符),然后又在每次dequeue过后将旧的约束移除,又从头开始重新添加约束。自动布局引擎内部并没有被设计来可以处理大规模的约束更改,你会看到大量的性能问题。iOS8 - Self-Sizing Cells3. 启用估算行高在iOS8上,苹果将许多在iOS8之前比较难实现的东西都内置实现了。为了让cell实现self-sizing的机制,必须先将tableView的rowHeight属性设置为常量UITableViewAutomaticDimension。然后,只需将tableView的estimatedRowHeight属性设置为非零值即可开启行高估算功能,例如: self.tableView.rowHeight = UITableViewAutomaticD
self.tableView.estimatedRowHeight = 44.0; // 设置为一个接近“平均”行高的值
这样做就为tableView上还没有显示在屏幕上的cell提供了一个临时的估算的行高。然后,当cell即将滚入屏幕范围内的时候,会计算出实际的高度。为了确定每一行的实际高度,tableView会自动让每个cell基于其contentView的已知固定宽度(tableView的宽度,减去其他额外的,像section index或accessoryView这些宽度)和被加到contentView及其子视图上的自动布局约束规则来计算contentView的高度。一旦真正的行高被计算出来后,旧的估算的行高会被更新为这个真实的行高(并且其他任何需要对tableView的contentSize或contentOffset的更改都自动替你完成了)。一般来说,行高估算值不需要太精确——它只是被用来修正tableView中滚动条的大小的,当你在屏幕上滑动cell的时候,即便估算值不准确,tableView还是能很好地调节滚动条。将tableView的estimatedRowHeight属性设置成(在viewDidLoad或类似的方法中)一个接近于“平均”行高的常量值即可。只有行高变化很极端的时候(比如相差一个数量级),才会在滚动时产生滚动条“跳跃”的现象。这个时候,你才应当实现tableView:estimatedHeightForRowAtIndexPath:方法,为每一行返回一个更精确的估算值。iOS7支持(需要自己实现cell尺寸自适应功能)3. 完成一个完整的布局过程 & 计算cell的高度首先,为每一个cell都初始化一个离屏(offscreen)实例,为每个重用标示符实例化一个与之对应的cell实例,这些cell完全用于高度计算。(离屏表示cell的引用被存储在view controller的一个属性或实例变量之中,并且这个cell绝对不会被用作tableView:cellForRowAtIndexPath:方法的返回值以实际呈现在屏幕上。)接着,这个cell的内容(例如,文本、图片等等)还必须和会被显示在table view中的内容完全一致。然后,强制cell立即更新子视图的布局,再用cell的contentView调用systemLayoutSizeFittingSize:方法计算出cell所需的高度是多少。使用UILayoutFittingCompressedSize参数可以得到适合cell中所有内容所需的最小尺寸。然后其高度就可以作为tableView:heightForRowAtIndexPath:方法的返回值。4. 使用估算的行高如果你的table view超过了几十行,你会发现自动布局约束的解决方式在第一次加载table view的时候会迅速地卡住主线程。因为,在第一次加载过程中,每一行都会调用tableView:heightForRowAtIndexPath:方法(为了计算滚动条的尺寸)。iOS7中,你可以(也绝对应该)使用table view的estimatedRowHeight属性。这样会为还不在屏幕范围内的cell提供一个临时估算的行高值。然后,当这些cell即将要滚入屏幕范围内的时候,真实的行高值会被计算出来(通过tableView:heightForRowAtIndexPath:方法),估算的行高就会被替换掉。一般来说,行高估算值不需要太精确——它只是被用来修正tableView中滚动条的大小的,当你在屏幕上滑动cell的时候,即便估算值不准确,tableView还是能很好地调节滚动条。将tableView的estimatedRowHeight属性设置成(在viewDidLoad或类似的方法中)一个接近于“平均”行高的常量值即可。只有行高变化很极端的时候(比如相差一个数量级),才会在滚动时产生滚动条“跳跃”的现象。这个时候,你才应当实现tableView:estimatedHeightForRowAtIndexPath:方法,为每一行返回一个更精确的估算值。5. 缓存行高(如果需要)如果上面提到的你都做了,但是tableView:heightForRowAtIndexPath:的性能仍然慢的不可接受。非常不幸,你需要给行高做一些缓存(这是苹果的工程师们给出的改进建议)。大体的思路是,第一次计算时让自动布局引擎解析约束条件,然后将计算出的行高缓存起来,以后所有对该cell的高度的请求都返回缓存值。当然,关键还要确保任何会导致cell高度变化的情况发生时你都清除了缓存的行高——这通常发生在cell的内容变化时或其他重大事件发生时(比如用户调节了动态类型文本大小(Dynamic Type text size)的滑动条)。iOS7示例代码(包含详细的注释)- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
// 判断indexPath对应cell的重用标示符,
// 取决于特定的布局需求(可能只有一个,也或者有多个)
NSString *reuseIdentifier = ...;
// 取出重用标示符对应的cell。
// 注意,如果重用池(reuse pool)里面没有可用的cell,这个方法会初始化并返回一个全新的cell,
// 因此不管怎样,此行代码过后,你会可以得到一个布局约束已经完全准备好,可以直接使用的cell。
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
// 用indexPath对应的数据内容来配置cell,例如:
// cell.textLabel.text = someTextForThisC
// 确保cell的布局约束被设置好了,因为它可能刚刚才被创建好。
// 使用下面两行代码,前提是假设你已经在cell的updateConstraints方法中设置好了约束:
[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];
// 如果你使用的是多行的UILabel,不要忘了,preferredMaxLayoutWidth需要设置正确。
// 如果你没有在cell的-[layoutSubviews]方法中设置,就在这里设置。
// cell.multiLineLabel.preferredMaxLayoutWidth = CGRectGetWidth(tableView.bounds);
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
// 判断indexPath对应cell的重用标示符,
NSString *reuseIdentifier = ...;
// 从cell字典中取出重用标示符对应的cell。如果没有,就创建一个新的然后存储在字典里面。
// 警告:不要调用table view的dequeueReusableCellWithIdentifier:方法,因为这会导致cell被创建了但是又未曾被tableView:cellForRowAtIndexPath:方法返回,会造成内存泄露!
UITableViewCell *cell = [self.offscreenCells objectForKey:reuseIdentifier];
if (!cell) {
cell = [[YourTableViewCellClass alloc] init];
[self.offscreenCells setObject:cell forKey:reuseIdentifier];
// 用indexPath对应的数据内容来配置cell,例如:
// cell.textLabel.text = someTextForThisC
// 确保cell的布局约束被设置好了,因为它可能刚刚才被创建好。
// 使用下面两行代码,前提是假设你已经在cell的updateConstraints方法中设置好了约束:
[cell setNeedsUpdateConstraints];
[cell updateConstraintsIfNeeded];
// 将cell的宽度设置为和tableView的宽度一样宽。
// 这点很重要。
// 如果cell的高度取决于table view的宽度(例如,多行的UILabel通过单词换行等方式),
// 那么这使得对于不同宽度的table view,我们都可以基于其宽度而得到cell的正确高度。
// 但是,我们不需要在-[tableView:cellForRowAtIndexPath]方法中做相同的处理,
// 因为,cell被用到table view中时,这是自动完成的。
// 也要注意,一些情况下,cell的最终宽度可能不等于table view的宽度。
// 例如当table view的右边显示了section index的时候,必须要减去这个宽度。
cell.bounds = CGRectMake(0.0f, 0.0f, CGRectGetWidth(tableView.bounds), CGRectGetHeight(cell.bounds));
// 触发cell的布局过程,会基于布局约束计算所有视图的frame。
// (注意,你必须要在cell的-[layoutSubviews]方法中给多行的UILabel设置好preferredMaxLayoutWidth值;
// 或者在下面2行代码前手动设置!)
[cell setNeedsLayout];
[cell layoutIfNeeded];
// 得到cell的contentView需要的真实高度
CGFloat height = [cell.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize].
// 要为cell的分割线加上额外的1pt高度。因为分隔线是被加在cell底边和contentView底边之间的。
height += 1.0f;
// 注意:除非行高极端变化并且你已经明显的觉察到了滚动时滚动条的“跳跃”现象,你才需要实现此方法;否则,直接用tableView的estimatedRowHeight属性即可。
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath{
// 以必需的最小计算量,返回一个实际高度数量级之内的估算行高。
if ([self isTallCellAtIndexPath:indexPath]) {
return 350.0f;
return 40.0f;
- iOS8以上才支持
- iOS7+来源:Coding With Objective-C原文地址:/blog//shi-yong-autolayoutshi-xian-uitableviewde-celldong-tai-bu-ju-he-ke-bian-xing-gao/
欢迎关注慕课网微信
12097 浏览
课程所用到的图片也在Github& 我的微博是 @林永坚Jake &如果你有问题请留言在慕课网,如果我未能及时回答,请在微博上 @我,请不要私信,因为我很少使用Web版的微博,看不到未关注人的私信。如果你喜欢这个课程,请告诉更多的人一起来学习,那样我们就可以制作更多Swift iOS 8 App开发的课程,你想学习Flappy Bird,Snapchat,Secret,Instagram,Tinder等App的开发吗?如果想请来多来支持支持,我们一起为大家创造更多实用的课程。
Copyright (C)
All Rights Reserved | 京ICP备 号-2下次自动登录
现在的位置:
& 综合 & 正文
我的Android进阶之旅——>Android常用计量单位(Dimension)的介绍(px,in,mm,pt,dp,dip,sp)
在Android开发中常用到px,in,mm,pt,dp,dip,sp这几个单位,你可不要混淆了
摘自:的一段简介
A dimension value defined in XML. A dimension is specified with a number followed by a unit of measure. For example: 10px, 2in, 5sp. The following units of measure are supported by Android:
Density-independent Pixels - An abstract unit that is based on the physical density of the screen. These units are relative to a 160 dpi (dots per inch) screen, on which 1dp is roughly equal to 1px. When running on a higher
density screen, the number of pixels used to draw 1dp is scaled up by a factor appropriate for the screen's dpi. Likewise, when on a lower density screen, the number of pixels used for 1dp is scaled down. The ratio of dp-to-pixel will change with the screen
density, but not necessarily in direct proportion. Using dp units (instead of px units) is a simple solution to making the view dimensions in your layout resize properly for different screen densities. In other words, it provides consistency for the real-world
sizes of your UI elements across different devices.
Scale-independent Pixels - This is like the dp unit, but it is also scaled by the user's font size preference. It is recommend you use this unit when specifying font sizes, so they will be adjusted for both the screen density
and the user's preference.
Points - 1/72 of an inch based on the physical size of the screen.
Pixels - Corresponds to actual pixels on the screen. This unit of measure is not recommended because the actual representation can each devices may have a different number of pixels per inch and may
have more or fewer total pixels available on the screen.
Millimeters - Based on the physical size of the screen.
Inches - Based on the physical size of the screen.
Note: A dimension is a simple resource that is referenced using the value provided in the name attribute (not the name of the XML file). As such, you can combine dimension
resources with other simple resources in the one XML file, under one &resources& element.
file location:
res/values/filename.xml
The filename is arbitrary. The &dimen& element's name will be used as the resource ID.
resource reference:
In Java: R.dimen.dimension_name
In XML: @[package:]dimen/dimension_name
&?xml version="1.0" encoding="utf-8"?&
name="dimension_name"
XML file saved at res/values/dimens.xml:
&?xml version="1.0" encoding="utf-8"?&
name="textview_height"25dp
name="textview_width"150dp
name="ball_radius"30dp
name="font_size"16sp
This application code retrieves a dimension:
Resources res = ;
float fontSize = res.(R.dimen.font_size);
This layout XML applies dimensions to attributes:
android:layout_height="@dimen/textview_height"
android:layout_width="@dimen/textview_width"
android:textSize="@dimen/font_size"
当然,英文看的头疼的话,可以看下面的中文介绍
device independent pixels(设备独立像素). 不同设备不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGA、HVGA和QVGA 推荐使用这个,不依赖像素。
在android上开发的将会在不同分辨率的手机上运行。为了让程序外观不至于相差太大,所以引入了dip的概念。比如定义一个矩形10 x 10dip.在分辨率为160dpi的屏上,比如G1,正好是10 x 10像素。而在240 dpi的屏,则是15 x 15像素.换算公式为pixs = dips * (density/160). density就是屏的分辨率
这里要特别注意dip与屏幕密度有关,而屏幕密度又与具体的硬件有关,硬件设置不正确,有可能导致dip不能正常显示。在屏幕密度为160的显示屏上,1dip=1px,有时候可能你的屏幕分辨率很大如480*800,但是屏幕密度没有正确设置比如说还是160,那么这个时候凡是使用dip的都会显示异常,基本都是显示过小。
dip的换算: dip(value)=(int) (px(value)/1.5 + 0.5)
dp (与密度无关的像素):同dip是一样的。 一种基于屏幕密度的抽象单位。在每英寸160点的显示器上,1dp = 1px。 dip 与dp相同,多用于android/ophone示例中。
pixels(像素)
屏幕上的点,不同设备不同的显示屏显示效果相同,这是绝对像素,是多少就永远是多少不会改变。一般我们HVGA代表320x480像素,这个用的比较多。
scaled pixels — best for text size (放大像素)(与刻度无关的像素):主要处理字体的大小。与dp类似,但是可以根据用户的字体大小首选项进行缩放。主要用于字体显示best for textsize。由此,根据 google 的建议,TextView 的字号最好使用 sp 做单位,而且查看TextView的源码可知 Android 默认使用 sp 作为字号单位。
使用建议:
根据google的推荐,像素统一使用dip,字体统一使用sp
为了使用户界面能够在现在和将来的显示器类型上正常显示,建议大家始终使用sp作为文字大小的单位,将dip作为其他元素的单位。当然,也可以考虑使用矢量图形,而不是用位图
如果 UI 能够以 sp 为单位提供设计是最好的,如果设计中没有 sp的概念,则开发人员也可以通过适当的换算取近似值。
过去,程序员通常以像素为单位设计计算机用户界面。例如,定义一个宽度为300像素的表单字段,列之间的间距为5个像素,图标大小为16×16像素 等。这样处理的问题在于,如果在一个每英寸点数(dpi)更高的新显示器上运行该程序,则用户界面会显得很小。在有些情况下,用户界面可能会小到难以看清内容。
与分辨率无关的度量单位可以解决这一问题。Android支持下列所有单位。
其他单位:(不经常用)
pt(磅) point,是一个标准的长度单位,1pt=1/72英寸,用于印刷业,非常简单易用;
在 Android 中,1pt 大概等于 2.22sp
inches(英寸):长度单位。
millimeters(毫米):长度单位。
dip和px 的关系:
density=0.75;
densityDpi=120;
QVGA(240*320)
density=1.0;
densityDpi=160;
HVGA(320*480)
density=1.0;
densityDpi=160;
VGA(480*640)
density=1.5;
densityDpi=240;
WVGA(480*800)
WQVGA:density=2.0;
densityDpi=120;
WQVGA(240*400)
PS:densityDip值表示每英寸有多少个显示点,与分辨率是两个概念
densityDpi=120时
屏幕实际分辨率为240px*400px (两个点对应一个分辨率)
状态栏和标题栏高各19px或者25dip
横屏是屏幕宽度400px 或者800dip,工作区域高度211px或者480dip
竖屏时屏幕宽度240px或者480dip,工作区域高度381px或者775dip
densityDpi=160时
屏幕实际分辨率为320px*533px (3个点对应两个分辨率)
状态栏和标题栏高个25px或者25dip
横屏是屏幕宽度533px 或者800dip,工作区域高度295px或者480dip
竖屏时屏幕宽度320px或者480dip,工作区域高度508px或者775dip
densityDpi=240时
屏幕实际分辨率为480px*800px (一个点对于一个分辨率)
状态栏和标题栏高个38px或者25dip
横屏是屏幕宽度800px 或者800dip,工作区域高度442px或者480dip
竖屏时屏幕宽度480px或者480dip,工作区域高度762px或者775dip
apk的资源包中
当屏幕densityDpi=240时,使用hdpi 标签的资源
当屏幕densityDpi=160时,使用mdpi标签的资源
当屏幕densityDpi=120时,使用ldpi标签的资源
不加任何标签的资源是各种分辨率情况下共用的
布局时尽量使用单位dip,少使用px
dp与px换算公式:
pixs =dips * (densityDpi/160).
dips=(pixs*160)/densityDpi
dp与px转换的方法:
public static int dip2px(Context context, float dipValue){
final float scale = context.getResources().getDisplayMetrics().
return (int)(dipValue * scale +0.5f);
public static int px2dip(Context context, float pxValue){
final float scale = context.getResource().getDisplayMetrics().
return (int)(pxValue / scale +0.5f);
480X272或400X240
分辨率(水平数×垂直数) 类型 比例
88×72 QQCIF 11:9
128×96 SUB-QCIF 4:3
128×128 知道的补上 1:1
160×120 QQVGA 4:3
176×144 QCIF 11:9
208×176 Sub-QVGA- 13:11
220×176 Sub-QVGA 5:4
240×176 Sub-QVGA+ 15:11
320×200 CGA 16:10
320×240 QVGA 4:3
352×288 CIF 11:9
640×360 nHD 4:3
400×240 WQVGA 5:3
400×320 WQVGA 5:4
480×240 WQVGA 2:1
480×272 WQVGA 16:9
480×320 HQVGA 3:2
640×480 VGA 4:3
640×350 EGA 64:35
720×480 VGA+ 3:2
768×576 PAL  
800×480 WVGA 5:3
854×480 FWVGA 16:9
800×600 SVGA 4:3
960×540 QHD 16:9
960×640 DVGA 3:2
WSVGA 128:75
WXGA 16:10
UxGA/XVGA 4:3
SXGA 25:16
WXGA+ 16:10
WSXGA 25:16
WSXGA 32:21
USVGA/UXGA/UGA 4:3
WSXGA+ 16:10
UXGA 19:12
WSUVGA+(WSUGA/HDTV) 4:3
WUXGA 16:10
SUVGA(QXGA) 4:3
UWXGA 16:10
WQUXGA 16:10
==================================================================================================
作者:欧阳鹏
欢迎转载,与人分享是进步的源泉!
转载请保留原文地址:
==================================================================================================
&&&&推荐文章:
【上篇】【下篇】 上传我的文档
 下载
 收藏
该文档贡献者很忙,什么也没留下。
 下载此文档
正在努力加载中...
LAYOUT的基本设置
下载积分:1900
内容提示:颜色设置是一个很重要的设置,它直接关系到设计中的观察效果&#4..
文档格式:PDF|
浏览次数:117|
上传日期: 16:49:38|
文档星级:
该用户还上传了这些文档
LAYOUT的基本设置
官方公共微信}

我要回帖

更多关于 layout是什么意思 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信