注意,本文的解决方案假定你:
a.使用storyboard或者xib;
b.使用autolayout自动布局;
c.使用swift而非Objective-C语言。
在进行产品开发的时候,我们经常遇到UI设计师给出1像素宽的间隔线。而这
种1像素宽的线,通常我们可以拖上一个view,将其宽或者高度设置为1。这在非
Retina屏上是没有问题的:1像素刚好对应的就是我们编程中的1个point,但在Retina
一个point则被映射成了2个像素,而在storyboard中设置约束或者frame的时候你是
没法设置小于1的值的,也即系统默认最小单位是1.该怎么办呢?
目前我想到了这样的一个方法:使用autolayout的情况下,在storyboard中,我
们按照一个点位(Point)布局我们的间隔线,这里我们用一个普通UIView将其宽度
或者高度约束设置为1(如果是横线设定高为1;如果竖线则定宽为1)。然后我们将
这个view的类名修改为我们定制的类名:SA01BorderLineView(继承自UIView)。
然后在这个类的重载方法layoutSubviews中,遍历其约束,找到定宽或者定高的约
束,根据屏幕是否是Retina屏来动态的修改约束的高度或者宽度值。
在下面的示例代码中,我们将通过对比普通view来看是否我们达到了预期效果:
首先定制一个SA01BorderLineView,直接继承自UIView,重载UIView的layoutSubviews
方法,遍历其约束,查找到定宽或者定高的约束(根据当前是横线还是竖线)。代
码如下:
@IBDesignable class SA01BorderLineView: UIView {
@IBInspectable var isHorizontal: Bool = false
override func layoutSubviews() {
super.layoutSubviews()
let layoutAttribute = self.isHorizontal ? NSLayoutAttribute.Height : NSLayoutAttribute.Width
for item in self.constraints() {
let constraint = item as NSLayoutConstraint
if constraint.firstItem as UIView == self && constraint.firstAttribute == layoutAttribute {
self.removeConstraint(constraint)
constraint.constant = 1 / UIScreen.mainScreen().scale
self.addConstraint(constraint)
}
}
}
}
注意代码中使用到了@IBInspectable和@IBDesignable,这两个关键字是swift
新引入的,用于定制的view等视图空间在xib或者storyboard中实现可视化定制新增
变量和实时渲染的功能。这里主要是因为我们引入了一个判断是否是横线的新增变量
:isHorizontal,想再storyboard中使用这个view的时候就能在storyboard中直接修改
它的值。截屏如下:
使用了IBInspectable关键字之后,能够在storyboard中直接修改相关属性值(方法1:通过runtime设置)
使用了IBInspectable关键字之后,能够在storyboard中直接修改相关属性值(方法2:通过类属性表设置)
示例代码github地址:https://github.com/lihux/iLihuxDailyAccumulates,该仓库包含
两个工程,源码在swift工程的accumulates->A001文件夹下。