首页 > 解决方案 > 自定义底部栏不在自定义分段控件的正确位置

问题描述

我正在尝试创建一个自定义,该自定义UISegmentedControl在所选选项下方的底部有一个栏。我添加了一个CALayer作为栏。更改所选选项后,栏不会移动到其预期位置

自定义代码UISegmentedControl如下-

class ProfileSegmentedControl: UISegmentedControl {
    private lazy var bottomBar = getBottomBar()

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

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

private extension ProfileSegmentedControl {
    func setup() {
        tintColor = .clear
        let normalAttributes: [NSAttributedString.Key: Any] = [
            .foregroundColor: UIColor.white,
            .font: UIFont.systemFont(ofSize: 16, weight: .medium)
        ]
        setTitleTextAttributes(normalAttributes, for: .normal)
        setTitleTextAttributes([.foregroundColor: UIColor(named: "black") as Any], for: .selected)
    }
}

private extension ProfileSegmentedControl {
    func getBottomBar() -> CALayer {
        let bar = CALayer()
        bar.backgroundColor = UIColor(named: "black")?.cgColor
        layer.addSublayer(bar)
        return bar
    }

    func setBarFrame() {
        let barWidth = bounds.width / CGFloat(numberOfSegments)
        let barHeight: CGFloat = 2
        let x = barWidth * CGFloat(selectedSegmentIndex)
        let y = bounds.height - barHeight

        bottomBar.frame = CGRect(x: x, y: y, width: barWidth, height: barHeight)
    }
}

extension ProfileSegmentedControl {
    override func layoutIfNeeded() {
        super.layoutIfNeeded()
        setBarFrame()
    }
}

将底部栏移动到预期位置需要点击 2 次选项。

谁能指出为什么会这样?谁能指出如何解决这个问题?

编辑-当视图首次加载并点击“Segment 0”时,栏出现在正确的位置,如下所示-

在此处输入图像描述

当点击“Segment 1”一次时,条形图不会移动,如下图所示 -

在此处输入图像描述

当再次点击“Segment 1”时,条形图将移动到正确的位置,如下所示 -

在此处输入图像描述

标签: iosswiftuisegmentedcontrol

解决方案


我认为这种方法行不通,因为在调用selectedSegmentIndex时尚未设置。layoutIfNeeded()这就是为什么您在点击 Seg-1 时会在 Seg-2 上加下划线,反之亦然。

我建议将您的覆盖替换为layoutIfNeeded()

extension ProfileSegmentedControl {

    override func layoutSubviews() {
        super.layoutSubviews()
        setBarFrame()
    }

}

然后添加一个valueChanged动作:

@IBAction func segmentChanged(_ sender: Any) {
    if let segControl = sender as? ProfileSegmentedControl {
        segControl.setNeedsLayout()
    }
}

据推测,您无论如何都在实施以在点击细分时采取行动。

这具有在控件宽度发生变化时自动调整条形的额外优势 - 例如在设备旋转时。


推荐阅读