ArcLayoutView: 一个弧形布局的实现

Posted 颐和园

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ArcLayoutView: 一个弧形布局的实现相关的知识,希望对你有一定的参考价值。

介绍

如果在项目中,设计师让你实现这样的效果 :

这会不会让你很抓狂呢? 别急,我们可以使用 ArcLayoutView。项目地址:https://gitee.com/kmyhy/arc-view

用法

其实就只有一个文件:ArcLayoutView.swift,把它放到你的项目中就好:)
编译时可能会出现两个宏找不到,你可以在 ViewController.swift 中找到它们:

let SCREEN_HEIGHT = UIScreen.main.bounds.height
let SCREEN_WIDTH = UIScreen.main.bounds.width

以及一个 UILabel 的扩展:

extension UILabel {
    func getSize(constrainedWidth: CGFloat) -> CGSize {
        return systemLayoutSizeFitting(CGSize(width: constrainedWidth, height: UIView.layoutFittingCompressedSize.height), withHorizontalFittingPriority: .required, verticalFittingPriority: .fittingSizeLevel)
    }
}

然后就可以创建一个 ArcLayoutView 对象并添加到你的 ViewController 中了(故事版或者代码添加)。如果你用的是故事版,那么别忘了为它创建相应的 IBOutlet 变量:

  @IBOutlet weak var arcView: ArcLayoutView!

然后你需要让 view controller 去实现 ArcLayoutViewDelegate 协议,它包含了 3 个方法:

extension ViewController: ArcViewDelegate {
    func itemView(_ index: Int) -> UIView {
        let itemView = CustomItemView(frame: .zero)
        itemView.titleLabel.text = titles[index]
        itemView.backgroundColor = .clear
        itemView.detailLabel.text = details[index]
        return itemView
    }
    
    func itemViewSize(_ itemView: UIView, limitWidth: CGFloat) -> CGSize {
        let v = itemView as! CustomItemView
        var labelSize = v.titleLabel.getSize(constrainedWidth: limitWidth-48)
        var h = labelSize.height
        labelSize = v.detailLabel.getSize(constrainedWidth: limitWidth-48)
        h += labelSize.height+2
        print(h)
        return CGSize(width: limitWidth, height: h)
    }
    
    func itemCount() -> Int {
        return titles.count
    }
}

其中,CustomItemView 是一个 UIView 或者自定义的 UIView 子类。 无论你用纯代码还是 xib 来创建都可以,这个随便你。

第一个委托方法需要返回一个 UIView 对象,对于本例,也就是 CustomItemView 对象了(这是 ArcLayoutView 的 ItemView,是它的 sub view,同时负责布局它们) 。同时需要在这个方法中渲染数据。

第二个委托方法需要返回 CGSize ,用于告诉 ArcLayoutView 每个 ItemView 占据多大的空间。如果 ItemView 自适应的,你需要正确计算出其大小并返回给 ArcLayoutView。

最后一个委托方法返回 Int,用于告诉 ArcLayoutView 它需要显示多少个 ItemView。

好了,让我们将 view controller 指定为 ArcLayoutView 的委托:

        arcView.options.alignment = .middle
        arcView.delegate = self

ArcLayoutView 的options 属性是一个 ArcLayoutViewOptions 结构体。它提供了很多用于控制 ArcLayoutView 布局和外观的选项。比如 alignment 用于指定其在布局 ItemView 的对齐方式,可以使用.top, .middle.bottom。如果用 .middle ,那么看起来像这个样子:

注意这行: arcView.delegate = self 会导致 ArcLayoutView 重绘它的所有ItemView

ArcLayoutViewOptions 还有一个 itemAlignment 属性,用于指定 ItemView 本身是如何对齐于锚点 anchor的。所谓锚点,其实就是图片中那些红色小点。默认这个属性值为 .middle。

如果设置 options.alignment = .top, 那么看起来是这个样子:

相邻两个 ItemView 之间的垂直间距是相等的,你可以通过 ArcLayoutViewOptions 的 itemVerticalSpan 属性进行调整。

如果你不需要绘制弧线、anchor 和辐线,那么可以修改这几个属性:

arcView.options.showDot = false
arcView.options.showArc = false
arcView.options.showSpokes = false

它看起来像这个样子:

更多细节,请查看源码。

以上是关于ArcLayoutView: 一个弧形布局的实现的主要内容,如果未能解决你的问题,请参考以下文章

Android 弧形菜单设计

安卓自定义半圆弧形菜单

安卓自定义半圆弧形菜单

安卓自定义弧形刻度选择器

安卓自定义弧形刻度选择器

弧形背景Android