美文网首页乔帮主的遗产
如何优雅地减少视图层级?

如何优雅地减少视图层级?

作者: 一意孤行的程序猿 | 来源:发表于2019-12-16 22:31 被阅读0次

在实际业务中,我们经常遇到一个业务控件,由几个小控件组合完成。比如用户头像组件:有头像图片、等级图片、红点提示视图等。为了提高封装性和重用性,一般都会自定义一个视图控件来添加这些小控件。这样有一个副作用就是增加了一层视图层级,如下图所示:

视图层级多了一层,在布局计算时会更加耗时。视图对象多了一个,内存消耗会更多。那有没有办法即保证了控件的封装性,又可以减少一层视图的包裹呢?答案就是它:UILayoutGuide,用了它之后的效果如下图:

减少了一层视图,但是显示效果和封装效果一样。

重要的事情讲三遍:
本方案仅提供一个有趣的思路,并不保证其性能!
本方案仅提供一个有趣的思路,并不保证其性能!
本方案仅提供一个有趣的思路,并不保证其性能!

LayoutContainer

LayoutContainerGithub地址

UILayoutGuide是iOS9引入的,就是为了解决需要有占位视图的场景。它不会出现在视图层级里面,也不会有视图对象,只会在布局引擎起作用。下面是官方注释可以细细品味:

UILayoutGuides will not show up in the view hierarchy, but may be used as items in an NSLayoutConstraint and represent a rectangle in the layout engine.

所以,创建继承UILayoutGuideLayoutContainer类,当做子控件的布局容器。子控件只需要相对LayoutContainer布局,就可以实现布局独立,达到其封装性。

LayoutContainer使用示例

LayoutContainer子类化示例

UserAvatarContainer就是用户头像的封装控件。内部的子控件,只需要相对self布局即可。

class UserAvatarContainer: LayoutContainer {
    lazy var avatarImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.image = UIImage(named: "lufei.jpg")
        imageView.contentMode = UIView.ContentMode.scaleAspectFill
        return imageView
    }()
    lazy var vipImageView: UIImageView = {
        let imageView = UIImageView()
        imageView.image = UIImage(named: "VIP")
        return imageView
    }()

    override func initializeViews() {
        super.initializeViews()

        avatarImageView.translatesAutoresizingMaskIntoConstraints = false
        avatarImageView.layer.masksToBounds = true
        //需要用owningView当做父视图
        owningView?.addSubview(avatarImageView)
        avatarImageView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
        avatarImageView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
        avatarImageView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
        avatarImageView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true

        vipImageView.translatesAutoresizingMaskIntoConstraints = false
        owningView?.addSubview(vipImageView)
        vipImageView.widthAnchor.constraint(equalToConstant: 30).isActive = true
        vipImageView.heightAnchor.constraint(equalToConstant: 30).isActive = true
        vipImageView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
        vipImageView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        //如果是通过约束布局,这里可以根据layoutFrame(不能使用frame、bounds、center)进行布局调整
        avatarImageView.layer.cornerRadius = layoutFrame.size.height/2
    }
}

添加LayoutContainer

class ListCell: UITableViewCell {
    lazy var avatarContainer: UserAvatarContainer = {
        UserAvatarContainer()
    }()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        contentView.addLayoutGuide(avatarContainer)
        avatarContainer.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 12).isActive = true
        avatarContainer.heightAnchor.constraint(equalToConstant: 100).isActive = true
        avatarContainer.widthAnchor.constraint(equalToConstant: 100).isActive = true
        avatarContainer.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
    }
}

注意事项

  • LayoutContainer的子视图需要在initializeViews方法里面进行初始化
  • LayoutContainer的子视图的布局在layoutSubviews进行调整
  • LayoutContainer仅能被addLayoutGuide一次,不允许被removeLayoutGuide。不然initializeViews会被调用多次,导致重复创建视图!

iOS学习栈(将持续更新)上

给大家推荐一个iOS技术交流群,群内提供数据结构与算法、底层进阶、swift、逆向、底层面试题整合文档等免费资料!!!可以加本人微信拉你进群!

收录:原文地址

相关文章

  • 如何优雅地减少视图层级?

    在实际业务中,我们经常遇到一个业务控件,由几个小控件组合完成。比如用户头像组件:有头像图片、等级图片、红点提示视图...

  • Android 布局优化方法

    1.尽可能的减少视图的层级 2.不用设置不必要的背景 3.用include增加视图的复用 4.用merge减少层级...

  • 布局优化include, viewstub, merge

    布局优化 1.include 视图引入,可以配合merge使用重用布局 2.merge 减少视图层级步骤如下:1、...

  • 再次拾起merge,include,viewStub

    减少视图层级 merge主要是进行UI布局的优化的,删除多余的层级,优化UI。多用于替换fr...

  • 性能优化

    如何更高效地使用 OkHttp Android之解析加载大图 cpu: 布局优化: 1.减少过度绘制,减少层级,同...

  • 3.2 视图的层级关系

    视图的层级关系 视图的层级关系1.png 视图的层级关系2.png

  • 如何在Swift中优雅地使用ReusableIdentifier

    原文:如何在Swift中优雅地使用ReusableIdentifier 苹果为了保准UITableView视图的性...

  • 自定义控件入门

    自定义控件的优势 对显示控件的完全控制权 使视图层级结构平面化,减少视图层级结构,提升程序性能 Demo 第一个自...

  • 1. 3D模型基础

    3D模型基础 层级(Hierarchy)视图 1.如何快速找到一个特定的游戏对象(聚焦选择的方法)?层级视图中双击...

  • tensorflow初学

    tensorflow 优化: 如何减少过拟合: dropout 正则化 减少隐含层的层级数目

网友评论

    本文标题:如何优雅地减少视图层级?

    本文链接:https://www.haomeiwen.com/subject/oyrjnctx.html