热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

iosautolayoutdemystified(一)

在开发过程中,你可以通过调用hasAmbiguousLayout来测试你的view约束是否足够的。这个会返回boolean值。如果有一个不同的frame就会返回yes,如果view

在开发过程中,你可以通过调用hasAmbiguousLayout 来测试你的view约束是否足够的。这个会返回boolean值。如果有一个不同的frame就会返回yes,如果view的约束完全指定了就会返回no。

这些结果是view指定的。例如,一个设定了完全约束的view他的子view有ambiguous layout但是此view却没有那么你就应该为每一个view单独测试layout是否存在ambiguouslayout。


Intrinsic Content Size 

使用auto layout,view的content扮演着非常重要的角色。每个view的intrinsicContentSize描述了不会剪切data的显示完整view content的最小空间。

例如一个image view,content size根据image显示的size设置。一个大的image需要一个大的固有的content size。想像一下的code。他将一个ios7标准的icon.png image来加载到一个image view中去并且报告view的固有content size。如你所想像的,size是60乘60 points。image的大小提供给了view。

UIImageView *iv = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Icon-60.png"]];

NSLog(@"%@", NSStringFromCGSize(iv.intrinsicContentSize)); 

对于button,固有的content size根据他的title而有不同。随着title grows或者shrinks,button的固有的content size也会调节来做适应。这个代码片段创建了一个button并且分配给他几个不同的title。在每个分配后报告了固有content size。

UIButton *button =

[UIButton buttonWithType:UIButtonTypeSystem];

// Longer title, Figure 1-7, middle image

[button setTitle:@"Hello World" forState:UIControlStateNormal];

NSLog(@"%@: %@", [button titleForState:UIControlStateNormal],

NSStringFromCGSize(button.intrinsicContentSize));

// Shorter title, Figure 1-7, bottom image

[button setTitle:@"On" forState:UIControlStateNormal];

NSLog(@"%@: %@", [button titleForState:UIControlStateNormal],

NSStringFromCGSize(button.intrinsicContentSize));

When run, this snippet outputs the following sizes:

2013-07-02 12:16:46.576 HelloWorld[69749:a0b] Hello World: {78, 30}

2013-07-02 12:16:46.577 HelloWorld[69749:a0b] On: {30, 30} 

 

hello world版本展示了一个更宽的固有content size,两者都用了同样的高度。这些值可以根据你自定义的font size和title text而有变化。

view的固有size允许auto layout***得匹配view得frame来适应原始得content。当一个view有一个固有的content size的时候,size占据两个属性中的一个。你可以,例如,将一个text-based控件或者一个image view放置到他的superview中。而且他的layout不会产生ambiguous。这个固有的content size加上location combine来实现完整的指定placement。当你改变一个view的固有contents时,你需要调用invalidateIntrinsicContentSize 来使得auto layout知道宠溺计算下一个layout。


Compression Resistance and Content Hugging 

同样的建议,compression resistance压缩阻力涉及一个view保护他的content的方式。一个有高compression resistance的view会防止shrinking,缩小。他不会允许content被裁剪。看以下的例子,约束想设置button width是40 points。


Compression resistance 压缩阻力描述了一个view如何尝试保存他的最小固有content size。图中上面的button有一个更高的压缩阻力值,下面的有一个low value。正如你看到的,高优先级确保上面的button保存他的固有content。下面的button阻力太低。resizing成功,bottom button压缩了并且剪切了text文本。bottom button的“don't clip”请求(就是compression resistance 优先级)仍然在那里。但是并没有重要到阻止将宽度设置为40的约束。auto layout经常遇到两个冲突的请求。当只有一个请求会成功时,他就会满足高优先级的那个。

你可以通过View > Utilities > Show Size Inspector > View > Content Compression Resistance 来指定view的压缩阻力。分别设置水平和垂直方向的。value从1(最低)到1,000(请求的优先级)不等。默认的是750.

[button setContentCompressionResistancePriority:500 forAxis:UILayoutConstraintAxisHorizontal]; 


view的content hugging priority 。这个涉及view来防止额外的padding在他的content周围出现或者stretching他的content。下图中的buttons被告知stretch。上面的button有一个高的content hugging priority。下面的button有一个低值。button pads他的content并且产生了变宽的效果。Content hugging defaults to 250. 

[button setContentHuggingPriority:501 forAxis:UILayoutConstraintAxisHorizontal] 


content hugging描述view匹配他的frame到他的content size的期望。一个strong hugging priority限制view增长过大超过他的现有的content。一个weak优先级可以允许viewstretch并且在一堆padding中隔离他的content。


Image Embellishments 

当你在你的pictures中包含装饰的时候比如shadows,sparkles,badges和其他的items来延伸到images的content外时,image的原始size可能不会再反应你想让auto layout来控制的方式。在auto layout中,约束决定view的size和placement。使用一个

几何图形元素叫做alignment rectangle对齐矩形。uikit api调用可以帮助你控制那个placement。布置


Alignment Rectangles 

随着程序员创建复杂的views,他们可以使用比如shadows,外部高亮,exterior highlights,雕刻线engraving lines,反光reflections。就像他们做的,这些特征经常被应用到绘制image中。不想frames,view的对齐矩形应当限制在一个core visual element中。他的大小应当保留unaf- fected就像new items绘制到view上。看下图,view绘制有shadow和badge标记。当布局这个view时,你想让auto layout 只关注core element-蓝色矩形的校准。而不是装饰物的校准。


试图的对齐矩形(center)严格涉及要被对齐的core visual element而不是装饰品。

中间的image高亮view的对齐矩形。这个矩形排除了所有的装饰物比如drop shadow和标记。

这个就是你想让auto layout考虑的部分。形成对比的contrast时右侧image显示的矩形。

这个版本包括所有的装饰品,扩展到了应当考虑对齐的view frame的外部。这些装饰品可能潜在抛弃view的对齐特征,例如他的中间,底部和右侧如果他们在layout时被考虑到。

使用alignment rectangles而不是frames,auto layout确保主要information像view的edges和center都会在layout中被考虑到。

在下图中,被装饰的view和背景网格完美的对齐。他的标记和shadow在摆放过程中却是不被考虑的。


auto layout仅仅会考虑view的对齐矩形当在他的superview中居中布局时。shadow和badge不会作用于他的placement。


Visualizing Alignment Rectangles 

ios和os x可以让你在应用程序中使用对齐矩形来叠加views。你从app的scheme中设置一个简单的加载参数:ios中UIViewShowAlignmentRects 和 os x中的NSViewShowAlignmentRects 。设置参数为yes并且使用dash破折号来作为前缀。当app运行时,矩形在每个view上显示。

 


Alignment Insets 

绘制艺术总是包含hard-coded部分比如高亮,shadows或者其他的。下图展示了当同auto layout一起使用image-based装饰品时候出现的典型的问题。左图展示了一个基本的image view,效果通过photoshop创建的。我使用了一个标准的drop shadow effect。

当添加到image view时,20乘20的区域脱离了view的对齐矩形。导致他有点儿太靠左上。在默认的执行中,image view并不清楚image包含装饰元素。你需要告知如何调整他的实质content这样对齐矩形就会只考虑core materials。

为了容纳shadow,你加载并且重新创建image。这分为两步。

首先,像平常一样加载图片。

然后,为image调用imageWithAlignmentRectInsets来产生新的版本来执行特定的插图。下图展示了一个20像素的shadow通过将对齐矩形嵌入到右下方。 

  

 

左图,image view在没有调整的情况下创建。离左上方太远了。而右面的image view正好居中。insets定义了距离上,左,下,右的矩形区域的距离。你使用这种方式来描述移动他们多远或者使用负值来使得他们移出矩形区域。这些insets保证了对齐矩形是正确的。

The fields are defined as follows:

typedef struct {

CGFloat top, left, bottom, right;

} UIEdgeInsets;

 

指定了对齐矩形insets后可以看到改善的图。

HelloWorld[53122:c07] Frame: {{70, 162}, {200, 200}}

HelloWorld[53122:c07] Intrinsic Content Size: {180, 180}

HelloWorld[53122:c07] Alignment Rect: {{70, 162}, {180, 180}} 

 手动设置这些insets是非常痛苦的,特别是如果你稍后可能会更新你的涂层。当你知道对齐矩形和重叠的image bounds时,你就可以自动计算你所需要的edge insets来传递给这个方法。listing 1-1定义了一个简单的inset builder。他确定对齐矩形距离每个parent 矩形edge的距离。返回一个UIEdgeInset结构来表示这些值。使用这个函数来创建你的core visuals insets。

UIEdgeInsets BuildInsets(

CGRect alignmentRect, CGRect imageBounds)

{

// Ensure alignment rect is fully within source

CGRect targetRect =

CGRectIntersection(alignmentRect, imageBounds);

// Calculate insets

UIEdgeInsets insets;

insets.left = CGRectGetMinX(targetRect) –

CGRectGetMinX(imageBounds);

insets.right = CGRectGetMaxX(imageBounds) –

CGRectGetMaxX(targetRect);

insets.top = CGRectGetMinY(targetRect) –

CGRectGetMinY(imageBounds);

insets.bottom = CGRectGetMaxY(imageBounds) –

CGRectGetMaxY(targetRect);

return insets;


Declaring Alignment Rectangles 

cocoa和cocoa touch提供几个额外的方式来汇报对齐几何学。你可以执行alignmentRectForFrame:, frameForAlignmentRect:, baselineOffsetFromBottom, and alignmentRectInsets. 这些方法允许你的views声明并且从code中转化对齐矩形。

你可以忽略对齐矩形和insets。

A few notes on these items:

■ alignmentRectForFrame: and frameForAlignmentRect: must always be mathematical inverses of each other. 



  • Most custom views only need to override alignmentRectInsets to report content location within their frame.



  • baselineOffsetFromBottom is available only for NSView and refers to the distance between the bottom of a view’s alignment rectangle and the view’s content baseline, such as that used for laying out text. This is important when you want to align views to text baselines and not to the lowest point reached by typographic descenders, like j and q. 




Implementing Alignment Rectangles 

listing 1-2提供了一个例子基于代码的对齐几何校正。这个os x app创建了一个fixed-size view并且绘制了一个shadowed rounded 举行区域在其中。当USE_ALIGNMENT_ RECTS设置为1时,他的alignmentRectForFrame和 frameForAlignmentRect:方法从frames和对齐矩形转化。1-15展示的这些方法允许view根据适合的对齐来显示。

@interface CustomView : NSView

@end

@implementation CustomView

- (void) drawRect:(NSRect)dirtyRect

{

NSBezierPath *path; 

// Calculate offset from frame for 170x170 art CGFloat dx = (self.frame.size.width - 170) / 2.0f; CGFloat dy = (self.frame.size.height - 170);

// Draw a shadow

NSRect rect = NSMakeRect(8 + dx, -8 + dy, 160, 160);

path = [NSBezierPath

bezierPathWithRoundedRect:rect xRadius:32 yRadius:32];

[[[NSColor blackColor] colorWithAlphaComponent:0.3f] set];

[path fill];

// Draw fixed-size shape with outline

rect.origin = CGPointMake(dx, dy);

path = [NSBezierPath

bezierPathWithRoundedRect:rect xRadius:32 yRadius:32];

[[NSColor blackColor] set];

path.lineWidth = 6;

[path stroke];

[ORANGE_COLOR set];

[path fill];

}

- (NSSize)intrinsicContentSize

{

// Fixed content size - base + frame

return NSMakeSize(170, 170);

}

#define USE_ALIGNMENT_RECTS 1

#if USE_ALIGNMENT_RECTS



  • -  (NSRect)frameForAlignmentRect:(NSRect)alignmentRect

    {

    // 1 + 10 / 160 = 1.0625

    NSRect rect = (NSRect){.origin = alignmentRect.origin};

    rect.size.width = alignmentRect.size.width * 1.06250;

    rect.size.height = alignmentRect.size.height * 1.06250;

    return rect;

    }



  • -  (NSRect)alignmentRectForFrame:(NSRect)frame

    {

    // Account for vertical flippage

    CGFloat dy = (frame.size.height – 170.0) / 2.0;

    rect.origin = CGPointMake(frame.origin.x, frame.origin.y + dy);

    rect.size.width = frame.size.width * (160.0 / 170.0);

    rect.size.height = frame.size.height * (160.0 / 170.0); 



return rect; }

#endif @end 


Figure 1-15 Implementing intrinsic content size and frame/alignment rect conversion methods ensures that your view will align and display correctly (as shown on the left) rather than be mis- aligned and possibly clipped (as shown on the right). 

 



推荐阅读
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 浏览器中的异常检测算法及其在深度学习中的应用
    本文介绍了在浏览器中进行异常检测的算法,包括统计学方法和机器学习方法,并探讨了异常检测在深度学习中的应用。异常检测在金融领域的信用卡欺诈、企业安全领域的非法入侵、IT运维中的设备维护时间点预测等方面具有广泛的应用。通过使用TensorFlow.js进行异常检测,可以实现对单变量和多变量异常的检测。统计学方法通过估计数据的分布概率来计算数据点的异常概率,而机器学习方法则通过训练数据来建立异常检测模型。 ... [详细]
  • iOS Swift中如何实现自动登录?
    本文介绍了在iOS Swift中如何实现自动登录的方法,包括使用故事板、SWRevealViewController等技术,以及解决用户注销后重新登录自动跳转到主页的问题。 ... [详细]
  • Android源码中的Builder模式及其作用
    本文主要解释了什么是Builder模式以及其作用,并结合Android源码来分析Builder模式的实现。Builder模式是将产品的设计、表示和构建进行分离,通过引入建造者角色,简化了构建复杂产品的流程,并且使得产品的构建可以灵活适应变化。使用Builder模式可以解决开发者需要关注产品表示和构建步骤的问题,并且当构建流程发生变化时,无需修改代码即可适配新的构建流程。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • Voicewo在线语音识别转换jQuery插件的特点和示例
    本文介绍了一款名为Voicewo的在线语音识别转换jQuery插件,该插件具有快速、架构、风格、扩展和兼容等特点,适合在互联网应用中使用。同时还提供了一个快速示例供开发人员参考。 ... [详细]
  • 展开全部下面的代码是创建一个立方体Thisexamplescreatesanddisplaysasimplebox.#Thefirstlineloadstheinit_disp ... [详细]
  • 拥抱Android Design Support Library新变化(导航视图、悬浮ActionBar)
    转载请注明明桑AndroidAndroid5.0Loollipop作为Android最重要的版本之一,为我们带来了全新的界面风格和设计语言。看起来很受欢迎࿰ ... [详细]
  • 有没有一种方法可以在不继承UIAlertController的子类或不涉及UIAlertActions的情况下 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • IOS开发之短信发送与拨打电话的方法详解
    本文详细介绍了在IOS开发中实现短信发送和拨打电话的两种方式,一种是使用系统底层发送,虽然无法自定义短信内容和返回原应用,但是简单方便;另一种是使用第三方框架发送,需要导入MessageUI头文件,并遵守MFMessageComposeViewControllerDelegate协议,可以实现自定义短信内容和返回原应用的功能。 ... [详细]
  • 本文介绍了pack布局管理器在Perl/Tk中的使用方法及注意事项。通过调用pack()方法,可以控制部件在显示窗口中的位置和大小。同时,本文还提到了在使用pack布局管理器时,应注意将部件分组以便在水平和垂直方向上进行堆放。此外,还介绍了使用Frame部件或Toplevel部件来组织部件在窗口内的方法。最后,本文强调了在使用pack布局管理器时,应避免在中间切换到grid布局管理器,以免造成混乱。 ... [详细]
  • C#多线程解决界面卡死问题的完美解决方案
    当界面需要在程序运行中不断更新数据时,使用多线程可以解决界面卡死的问题。一个主线程创建界面,使用一个子线程执行程序并更新主界面,可以避免卡死现象。本文分享了一个例子,供大家参考。 ... [详细]
author-avatar
水急送_113
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有