首页 > 解决方案 > SegmentedControl 的新 iOS13 外观是否可供公众使用

问题描述

我在 iOS 13 演示文稿中看到了 UISegmentedControl 的这种风格,我想知道它是否也可供公众使用,或者我需要自己自定义 SegmentedControl 来实现这一点:

在此处输入图像描述

标签: iosswiftxcodeuikituisegmentedcontrol

解决方案


是的,我已经尽可能地做了类似的东西,所以我以任何一种方式分享它,只有一个问题是这不能很好地调整大小并且更适合静态项目列表

@IBDesignable
class BlurredSegmentedControl: UIView {
    var delegate:TabBarDelegate?
    static var segmentInset: CGFloat = 4
    static var cornerRadius: CGFloat = 15

    let segmentedControl: UISegmentedControl = {
        let control = UISegmentedControl()
        control.backgroundColor = .clear
        control.tintColor = .clear
        control.setTitleTextAttributes([
            NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14) as Any,
            NSAttributedString.Key.foregroundColor: UIColor.lightGray
            ], for: .normal)
        control.setTitleTextAttributes([
            NSAttributedString.Key.font: UIFont.systemFont(ofSize: 14) as Any,
            NSAttributedString.Key.foregroundColor: UIColor.white
            ], for: .selected)
        control.translatesAutoresizingMaskIntoConstraints = false
        return control
    }()
    let bacgroundView: UIView = {
        let blurEffect = UIBlurEffect(style: UIBlurEffect.Style.dark)
        let blurEffectView = UIVisualEffectView(effect: blurEffect)
        blurEffectView.layer.cornerRadius = cornerRadius + (segmentInset / 2)
        blurEffectView.clipsToBounds = true
        blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        blurEffectView.translatesAutoresizingMaskIntoConstraints = false
        return blurEffectView
    }()
    let bottomBar: UIView = {
        let blurEffect = UIBlurEffect(style: UIBlurEffect.Style.light)
        let blurEffectView = UIVisualEffectView(effect: blurEffect)
        blurEffectView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        blurEffectView.layer.cornerRadius = cornerRadius
        blurEffectView.clipsToBounds = true
        blurEffectView.translatesAutoresizingMaskIntoConstraints = false
        return blurEffectView
    }()

    @IBInspectable
    var segmentItems: [String] = [] {
        didSet {
            guard segmentItems.count > 0 else { return }
            setupSegmentItems()
        }
    }

    var bottomBarWidthAnchor: NSLayoutConstraint?

    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setup()
    }

    private func setup() {
        addSubview(bacgroundView)
        addSubview(bottomBar)
        addSubview(segmentedControl)
        bacgroundView.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
        bacgroundView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
        bacgroundView.topAnchor.constraint(equalTo: topAnchor).isActive = true
        bacgroundView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
        segmentedControl.widthAnchor.constraint(equalTo: widthAnchor, constant: -2 * BlurredSegmentedControl.segmentInset).isActive = true
        segmentedControl.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
        segmentedControl.topAnchor.constraint(equalTo: topAnchor, constant: BlurredSegmentedControl.segmentInset).isActive = true
        segmentedControl.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -1 * BlurredSegmentedControl.segmentInset).isActive = true
        segmentedControl.addTarget(self, action: #selector(segmentedControlValueChanged(_:)), for: .valueChanged)
        bottomBar.topAnchor.constraint(equalTo: topAnchor, constant: BlurredSegmentedControl.segmentInset).isActive = true
        bottomBar.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -1 * BlurredSegmentedControl.segmentInset).isActive = true
        bottomBar.leftAnchor.constraint(equalTo: leftAnchor, constant: BlurredSegmentedControl.segmentInset).isActive = true
        setupSegmentItems()
    }

    private func setupSegmentItems() {
        if(segmentItems.count < 1) { return }
        segmentedControl.removeAllSegments()
        for (index, value) in segmentItems.enumerated() {
            segmentedControl.insertSegment(withTitle: value, at: index, animated: true)
        }
        segmentedControl.selectedSegmentIndex = 0
        bottomBarWidthAnchor?.isActive = false
        bottomBarWidthAnchor = bottomBar.widthAnchor.constraint(equalTo: segmentedControl.widthAnchor, multiplier: 1 / CGFloat(segmentItems.count))
        bottomBarWidthAnchor?.isActive = true
        delegate?.selectedTabItem(title: segmentItems[0])
    }

    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        setup()
    }

    @objc func segmentedControlValueChanged(_ sender: UISegmentedControl) {
        delegate?.selectedTabItem(title: segmentItems[self.segmentedControl.selectedSegmentIndex])
        UIView.animate(withDuration: 0.3) {
            var offset: CGFloat = 0
            if self.segmentedControl.selectedSegmentIndex == 0 {
                offset = BlurredSegmentedControl.segmentInset
            }
            if self.segmentedControl.selectedSegmentIndex == self.segmentItems.count - 1 {
                offset = (1 * BlurredSegmentedControl.segmentInset)
            }
            let originX = ((self.segmentedControl.frame.width / CGFloat(self.segmentItems.count)) * CGFloat(self.segmentedControl.selectedSegmentIndex)) + offset
            self.bottomBar.frame.origin.x = originX
        }
    }
}

推荐阅读