简单的基于组合的 Custom View (Swift) 示例

2015-06-07 01:29:06 +08:00
 banxi1988

简单的基于组合的Custom View 示例 - 一个前面带一个 Icon 的 TextField的简单实现

需求

一个项目中很多地方都用到这种一个Icon 后面跟着一个TextField的 UI. 因为 Xcode 不支持这种界面上的重用.
而且就是是Copy and Paste也是有问题的,因为Copy进,View的约束并不会跟着走
为了避免重复劳动 ,就只要写一个简单的Custom View来实现了.

代码分析:

完整源代码见: https://gist.github.com/banxi1988/d31c7a41f29e7ddca728

  1. @IBDesignable - 自定义View的类声明没有此属性的话,Interface Builder 中的预览界面是显示不出来的.
  2. 可以通过prepareForInterfaceBuilder()方法来设置,只在开发时可用的初始值, 注意在开发时的,资源加载需要多写的代码.如:
override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        let bundle = NSBundle(forClass: self.dynamicType)
        let image = UIImage(named: "icon_locate", inBundle: bundle, compatibleWithTraitCollection: self.traitCollection)
        iconImageView.image = image
        textField.text = "大学英语四级"
        backgroundColor = UIColor.lightGrayColor()
    }
  1. 注意重写 instrinsicContentSize() 一般的实现逻辑的,遍历,组合,比较,求和.
override func intrinsicContentSize() -> CGSize {
        let iconSize = iconImageView.intrinsicContentSize()
        let textSize = textField.intrinsicContentSize()

        let width  = padding.left + iconSize.width + iconPadding + textSize.width + padding.right
        let height = padding.top + max(iconSize.height, textSize.height) + padding.bottom
        return CGSize(width: width, height: height)
    }
  1. 设置AutoLayout约束时,值得注意:
    4.1 除非确实需要,不要忘记调用 iconImageView.setTranslatesAutoresizingMaskIntoConstraints(false)
    4.2 设置好contentHuggingPriority,和 contentResistancePriority
    如这里,在整个UI控制伸长时,先让textField变长
    textField.setContentHuggingPriority(240, forAxis: UILayoutConstraintAxis.Horizontal)

  2. 当组合中的子控件的内容发生了变化,正确做法是应该调用:
    invalidateIntrinsicContentSize()

  3. @IBInspectable 属性目前不建议使用,用一次卡一次
    如果取消不用了,记得将IB中控件属性的这些自定义属性,删除.

PS:
问: 标题是基于组合的Custom View 那还有基于其他的吗?
答: 有,还有基于继承,然后主要是 自定义 drawRect 方法,或者自定义 CALayer
当然,更多是两者都基于.

希望对大家有用.

2614 次点击
所在节点    iDev
7 条回复
ruandao
2015-06-07 03:15:53 +08:00
楼主,请教下,如何设置标准的ImageView的控件(符合contentMode的控件, 默认ImageView 的intrinsicContentSize返回的是Image的size, 但是,当ImageView的宽度受限的时候,intrinsicContentSize 并没有根据contentMode 返回对应的值)

xib 里面的imageView 的intrinsicContentSize 里面默认返回的是 image的size, 这样,导致当宽度达不到image的宽度的时候,高度扔进使用image的高度

恩, 我做了个简单的 demo 来演示

https://github.com/ruandao/kkk


黄色是需要去除的
谢谢
banxi1988
2015-06-07 08:38:31 +08:00
@ruandao 你的demo我看了.
imageView 返回的 instrinsicContentSize 返回的是图片的大小,这没有错.
如果你想限制imageView的frame 大小, 你可以设置宽度及高度的约束啊.
blank_dlh
2015-06-07 11:05:35 +08:00
不是能设置 UITextField 的 leftView 吗 - -
ruandao
2015-06-07 12:39:16 +08:00
@banxi1988
恩, 但是宽度约束不确定,是由周围的label 确定的
banxi1988
2015-06-07 23:11:04 +08:00
@blank_dlh 谢谢提醒,我突然想起来还有这个,一时忘记了.
不过,在我界面需要下使用leftView是无法实现的.
首先对于icon的位置没有提供接口. 而且leftView 是内联的. 在某些情况下, leftView 应该会是更好的选择.
banxi1988
2015-06-08 08:27:23 +08:00
@ruandao 宽度约束是动态的确实的,那你可以使用图片的宽高比的约束. 如果是在Inteface Builder中叫
Aspect Ratio
ruandao
2015-06-09 00:58:31 +08:00
@banxi1988

恩, 谢谢 倒是没意识到这个

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/196638

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX