美文网首页iOS常用iOS
优雅的使用UIStackView

优雅的使用UIStackView

作者: 啧啧同学 | 来源:发表于2020-08-05 07:14 被阅读0次

UIStackView是iOS9苹果在UIKit框架中引入了一个新的视图类,开发者仅需设置很少,甚者不需要设置任何的约束就可以快速地实现子视图的均匀布局

值得注意的是,UIStackView虽然继承自UIView,但是并不参与屏幕的渲染,重写drawRect:方法也是无效的。

UIStackView的特有属性四个:
  • Axis
  • Distribution
  • Alignment
  • spacing

添加子视图的方式

UIStackView使用arrangedSubviews数组来管理子视图。需要注意的是这个数组是一个readonly的属性,我们需要调用方法对arrangedSubviews数组进行操作。

UIStackView的应用--封装一个文件工具操作类

枚举 + UIScrollView + UIStackView 配合使用

1.先提前设计该工具类创建及调用的方式

   
        let view = FCFileToolView(categorys: [.deleted, .copy]) { (category) in
            switch category {
            case .deleted:
                      delete()
            case .copy: break
                      copy()
            default:
                    other()
            }
        }

根据调用方的需求, 定义枚举FCFileToolsCategory:此处是文件操作,定义 全选、删除、分享、下载、复制、文件转移六种操作;并根据ui,枚举内定义各种操作对应的title及icon 属性(个人觉得这是 swift enum中最帅的特性)

enum FCFileToolsCategory {

    case selectedAll(Bool)//全选
    case deleted//删除
    case share//分享
    case download//下载
    case copy//复制
    case move(String)// 文件转移

    //展示title
    var displayTitle: String {
        switch self {
        case .selectedAll(let isSelected):
            return isSelected ? "取消全选".local() : "全选".local()
        case .deleted:
            return "删除".local()
        case .share:
            return "分享".local()
        case .download:
            return "保存至相簿".local()
        case .copy:
            return "拷贝照片".local()
        case .move(_):
            return "移动文件".local()
        }
    }
    
   // 展示用的图标
    var displayIcon: String {
        
        switch self {
        case .selectedAll(_):
            return "icon_file_edit"
        case .deleted:
            return "icon_file_delete"
        case .share:
            return "icon_file_shared"
        case .download:
            return "icon_file_download"
        case .copy:
            return "icon_file_copy"
        case .move(_):
            return "icon_file_move"
        }
    }
}

2.封装加载用的ItemView及对应的viewModel

class FCFileToolsViewModel {

    var category: FCFileToolsCategory
    var closure: (() -> ())?
    
    init(category: FCFileToolsCategory) {
        self.category = category
    }
}

class FCFileToolsView: UIView {

    init(_ model: FCFileToolsViewModel) {
        self.model = model
        super.init(frame: .zero)
        
        setupSubViews()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func setupSubViews() {
        
        addSubview(icon)
        addSubview(titleLabel)
        addSubview(bgBtn)
        
        icon.snp.makeConstraints { (make) in
            make.top.equalToSuperview()
            make.width.equalTo(16.0)
            make.height.equalTo(18.0)
            make.left.right.equalToSuperview().inset(10.0)
        }
        
        titleLabel.snp.makeConstraints { (make) in
            make.top.equalTo(icon.snp.bottom).offset(2.0)
            make.left.right.equalToSuperview().inset(2.0)
            make.bottom.equalToSuperview()
        }
        
        bgBtn.snp.makeConstraints { (make) in
            make.edges.equalToSuperview()
        }
        
        icon.image = UIImage(named: model.category.displayIcon)
        titleLabel.text = model.category.displayTitle
        
        themeConfig { (v, t) in
            guard let view = v as? FCFileToolsView, let theme = t as? FCThemeColor else { return }
            
            view.backgroundColor = .clear
            view.titleLabel.textColor = theme.textColorSubTitle
        }
    }
    
    @objc func onBgClickEvent() {
        
        switch model.category {
            
        case .selectedAll(let isSelected):
            
            model.category = .selectedAll(!isSelected)
            titleLabel.text = model.category.displayTitle
            
        default: break
        }
        
        model.closure?()
    }
    

    //MARK: - Property
    var model: FCFileToolsViewModel
    
    lazy var icon: UIImageView = {
        let imgV = UIImageView()
        imgV.contentMode = .scaleAspectFit
        return imgV
    }()
    
    lazy var titleLabel: UILabel = {
        let label = UILabel()
        label.textAlignment = .center
        label.font = UIFont.medium(10.0)
        label.numberOfLines = 0
        label.adjustsFontSizeToFitWidth = true
        return label
    }()
    
    lazy var bgBtn: UIButton = {
        let btn = UIButton()
        btn.backgroundColor = .clear
        btn.addTarget(self, action: #selector(onBgClickEvent), for: .touchUpInside)
        return btn
    }()
}

3.根据需求,创建好类及对应的viewModel

//可读性,closure使用别名
typealias FCFileToolClosure = (FCFileToolsCategory) -> ()

class FCFileToolViewModel {
    
    init(categorys: [FCFileToolsCategory], closure: @escaping FCFileToolClosure) {
        self.categorys = categorys
        self.closure = closure
    }
    
    //MARK: Property
    let categorys: [FCFileToolsCategory]
    let closure: FCFileToolClosure
}

class FCFileToolView: UIView {

    override init(frame: CGRect) {
        super.init(frame: frame)
        
        setupSubViews()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func setupSubViews() {
        
        addSubview(scrollView)
        scrollView.addSubview(listView)
        
        scrollView.snp.makeConstraints { (make) in
            make.edges.equalToSuperview()
        }
        
        listView.snp.makeConstraints { (make) in
            make.edges.equalToSuperview()
        }
    }
    
    func refreshUI(_ model: FCFileToolViewModel) {
        
        // 刷新前需要移除上次加载的item
        listView.subviews.forEach { $0.removeFromSuperview() }
        
        let toolViews: [FCFileToolsView] = model.categorys.compactMap { (category) -> FCFileToolsView in
            
            let subModel = FCFileToolsViewModel(category: category)
            
            subModel.closure = {
                
                model.closure(category)
            }
            
            let subView = FCFileToolsView(subModel)
            
            return subView
        }
        
        toolViews.forEach {
            listView.addArrangedSubview($0)
        }
    }
    
    //MARK: Property
    
    lazy var scrollView: UIScrollView = {
        let view = UIScrollView(frame: .zero)
        view.backgroundColor = .clear
        view.showsHorizontalScrollIndicator = false
        view.showsVerticalScrollIndicator = false
        view.bounces = false
        return view
    }()
    
    lazy var listView: UIStackView = {
        let view = UIStackView()
        view.distribution = .equalCentering
        view.alignment = .center
        view.backgroundColor = .clear
        view.spacing = 40.0
        view.axis = .horizontal
        return view
    }()
}

  1. 使用方式

    let listModel = FCFileToolViewModel(categorys: [.copy, .deleted, .move("")]) { (category) in
        
             //doMethod with category
    }
    
    let view = FCFileToolView()
    view.refreshUI(listModel)
    

//categorys 数量及顺序均可随意切换,超过限制宽度,可滑动
效果图如下:

IMG_0906.PNG

向右滑动后


IMG_0907.PNG

相关文章

  • 优雅的使用UIStackView

    UIStackView是iOS9苹果在UIKit框架中引入了一个新的视图类,开发者仅需设置很少,甚者不需要设置任何...

  • UIStackView 使用

    UIStackView 只支持iOS9之后的版本,然而现在应用一般支持到iOS7,FDStackView,It w...

  • UIStackView使用

    什么是UIStackView? UIStackView是在iOS9中才出现的,它可以帮助我们布局UI控件,从而减少...

  • UIStackView使用

    UIStackView的使用 隐藏状态栏,设置 View controller-based status bar ...

  • UIStackView 使用

    为什么使用它 1.动态实现视图的添加。不用修改删除、添加、隐藏后的布局约束。2.布局速度快, 不需要写autola...

  • UIStackView的使用

    终于熬到了iOS9.0,如果你们公司最低支持的是iOS9的话。那么UIStackView就可以使用了。 由于UIS...

  • UIStackView的使用

    一、了解 instric content size instric content size 表示一个 view ...

  • iOS - UIStackView的使用

    UIStackView 在iOS9中苹果在UIKit框架中引入了一个新的视图类UIStackView。UIStac...

  • iOS UIStackView的使用

    效果图如下:

  • UIStackView使用(二)

    与Label、Button等控件一样,Stack View 也有自己的Intrinsic Size,在未设定约束时...

网友评论

    本文标题:优雅的使用UIStackView

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