首页 > 代码库 > SA001-借助IBInspectable和约束定制1像素宽的线(view)

SA001-借助IBInspectable和约束定制1像素宽的线(view)

        注意,本文的解决方案假定你:

        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文件夹下。

SA001-借助IBInspectable和约束定制1像素宽的线(view)