iOS Swift纯代码如何在容器视图中添加带标签的离散UISlider
实现方案推荐
你当前仅需要展示单个滑块+配套标签,不需要使用UITableView或UICollectionView,这两个组件是为列表类多内容场景设计的,单组件场景直接自定义UIView封装滑块和标签即可,实现更轻量也更易维护。
第一步:自定义滑块容器视图
直接封装所有滑块相关组件,代码如下:
class SliderContainerView: UIView { // 对外暴露滑块供外部配置事件 let discreteSlider: UISlider = { let slider = UISlider() slider.minimumValue = 1 slider.maximumValue = 5 slider.isContinuous = true slider.tintColor = .purple slider.translatesAutoresizingMaskIntoConstraints = false return slider }() private let minLabel: UILabel = { let label = UILabel() label.text = "Min" label.font = .systemFont(ofSize: 14) label.textColor = .secondaryLabel label.translatesAutoresizingMaskIntoConstraints = false return label }() private let maxLabel: UILabel = { let label = UILabel() label.text = "Max" label.font = .systemFont(ofSize: 14) label.textColor = .secondaryLabel label.translatesAutoresizingMaskIntoConstraints = false return label }() let currentValueLabel: UILabel = { let label = UILabel() label.text = "2" // 默认值和滑块初始值对应 label.font = .systemFont(ofSize: 16, weight: .medium) label.textColor = .label label.translatesAutoresizingMaskIntoConstraints = false return label }() override init(frame: CGRect) { super.init(frame: frame) setupLayout() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } private func setupLayout() { addSubview(discreteSlider) addSubview(minLabel) addSubview(maxLabel) addSubview(currentValueLabel) NSLayoutConstraint.activate([ // 当前值标签在顶部居中 currentValueLabel.topAnchor.constraint(equalTo: topAnchor, constant: 8), currentValueLabel.centerXAnchor.constraint(equalTo: centerXAnchor), // 滑块在当前值标签下方 discreteSlider.topAnchor.constraint(equalTo: currentValueLabel.bottomAnchor, constant: 16), discreteSlider.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 32), discreteSlider.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -32), // min标签在滑块左下角 minLabel.topAnchor.constraint(equalTo: discreteSlider.bottomAnchor, constant: 8), minLabel.leadingAnchor.constraint(equalTo: discreteSlider.leadingAnchor), // max标签在滑块右下角 maxLabel.topAnchor.constraint(equalTo: discreteSlider.bottomAnchor, constant: 8), maxLabel.trailingAnchor.constraint(equalTo: discreteSlider.trailingAnchor), // 容器底部约束 bottomAnchor.constraint(equalTo: minLabel.bottomAnchor, constant: 8) ]) } }
第二步:修改原控制器代码
替换你原来的sliderView定义,修改setupView逻辑:
// 替换原来的sliderView和discreteSlider定义 private let sliderContainer = SliderContainerView() private let step: Float = 1
setupView方法修改:
private func setUpView() { // 配置滑块容器 sliderContainer.translatesAutoresizingMaskIntoConstraints = false // 添加滑块值变化事件 sliderContainer.discreteSlider.addTarget(self, action: #selector(sliderValueDidChange(_:)), for: .valueChanged) // 设置初始值动画 UIView.animate(withDuration: 0.8) { self.sliderContainer.discreteSlider.setValue(2.0, animated: true) } // 直接添加到主视图,不需要tableView view.addSubviews(headerView, sliderContainer, footerView) headerView.title = "View Title" // 给sliderContainer加AutoLayout约束,放在header和footer中间即可 NSLayoutConstraint.activate([ sliderContainer.leadingAnchor.constraint(equalTo: view.leadingAnchor), sliderContainer.trailingAnchor.constraint(equalTo: view.trailingAnchor), sliderContainer.centerYAnchor.constraint(equalTo: view.centerYAnchor) // 可以根据需求调整位置 ]) }
第三步:完善滑块值变化逻辑,实现步长吸附+数值更新
@objc private func sliderValueDidChange(_ sender: UISlider) { // 步长吸附逻辑 let roundedValue = round(sender.value / step) * step sender.setValue(roundedValue, animated: false) // 更新当前值标签 sliderContainer.currentValueLabel.text = "\(Int(roundedValue))" }
如果你确实需要使用UITableView的实现方案
如果后续有其他列表内容需要和滑块一起展示,可以自定义UITableViewCell存放上面的SliderContainerView:
- 自定义SliderCell:
class SliderCell: UITableViewCell { let sliderContainer = SliderContainerView() override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) backgroundColor = .clear selectionStyle = .none sliderContainer.translatesAutoresizingMaskIntoConstraints = false contentView.addSubview(sliderContainer) NSLayoutConstraint.activate([ sliderContainer.topAnchor.constraint(equalTo: contentView.topAnchor), sliderContainer.leadingAnchor.constraint(equalTo: contentView.leadingAnchor), sliderContainer.trailingAnchor.constraint(equalTo: contentView.trailingAnchor), sliderContainer.bottomAnchor.constraint(equalTo: contentView.bottomAnchor) ]) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
- 修改tableView注册逻辑,把
SliderCell注册进去,在cellForRowAt对应行返回SliderCell即可,不需要做额外配置。
说明:UICollectionView在此场景下没有优势,它适用于多列布局、复杂自定义布局的列表场景,单组件或普通列表用上面两种方案即可。
内容的提问来源于stack exchange,提问作者John Szatmari
相关产品推荐
相关产品推荐

