【问题标题】:Placing Labels above UISlider using UIStackView使用 UIStackView 在 UISlider 上方放置标签
【发布时间】:2018-08-24 20:25:58
【问题描述】:

我们正在尝试为以下场景寻找仅故事板的解决方案:

我们想在 UISlider 上方设置“里程碑”/“步骤”标签。值为 0.2 的拇指位置应恰好位于其上方相应标签的中间。重要的是标签位置将根据屏幕进行调整,因此约束需要成比例。插图:

我们尝试了什么:

我们将 UIStackView 与 7 个排列的子视图(每个步骤一个)放在 Slider 上方,并使其更宽一些(1.14 倍的 Slider 宽度,故意扩大 1/7)。出于某种原因,它在某些步骤上对齐,而在其他步骤上不对齐。示例:

任何关于为什么要解决它的建议或建议,将不胜感激。谢谢!

最好的问候,罗伊

【问题讨论】:

  • 我认为你应该创建自己的滑块控件
  • 嘿@ReinierMelian 感谢您的回复。我考虑过,但我很确定它是可以解决的,而且构建一个全新的只是在它上面放置标签是一种矫枉过正(这不会影响触摸事件,它只是 UI 相关的标签)
  • 您需要考虑拇指宽度,我认为在开始之前和结束之后添加 (thumb width)/2 作为空格
  • 作为栈宽约束常量? @ReinierMelian
  • 有可能,因为前导和尾随固定在滑块上

标签: ios autolayout storyboard uilabel uistackview


【解决方案1】:

Complete Playground source available here

如果您继承UISlider,您可以覆盖thumbRect(forBounds:trackRect:value:) 方法,该方法允许您调整显示拇指图像的矩形。这样做,并使其定位拇指图像它的中心在轨道上的相应点上。

override func thumbRect(forBounds bounds: CGRect, trackRect rect: CGRect, value: Float) -> CGRect {
    let superThumbRect = super.thumbRect(forBounds: bounds, trackRect: rect, value: value)
    let valueAsDecimalFraction = value == minimumValue ? 0 : (value - minimumValue)/(maximumValue - minimumValue)
    let valueAsDecimalFractionOfMinusOneToOne = (valueAsDecimalFraction*2 - 1)/2
    let xOffset = CGFloat(valueAsDecimalFractionOfMinusOneToOne) * superThumbRect.width
    return CGRect(
        x: superThumbRect.origin.x + xOffset,
        y: superThumbRect.origin.y,
        width: superThumbRect.size.width,
        height: superThumbRect.size.height)
}

一旦您覆盖了thumbRect(forBounds:trackRect:value:),您将看到拇指图像现在具有正确的行为,除了现在当滑块处于最小值或最大值时它挂在视图之外。要解决此问题,请覆盖 trackRect(forBounds:) 方法,以便将轨道填充一些允许拇指图像保持在滑块范围内的值。

let padding = CGFloat(18)

override func trackRect(forBounds bounds: CGRect) -> CGRect {
    let superTrackRect = super.trackRect(forBounds: bounds)
    return CGRect(
        x: superTrackRect.origin.x + padding,
        y: superTrackRect.origin.y,
        width: superTrackRect.size.width - padding*2,
        height: superTrackRect.size.height)
}

您可能很难使用UIStackView 定位UILabels - 标签的中心点不会位于正确的位置。相反,使用相对于滑块的约束来布局标签。

// Assuming labels: [UILabel], and a value of thumbIndent

override func viewWillLayoutSubviews() {
    let labelConstraints = labels.enumerated().map { (i, label) -> [NSLayoutConstraint] in
        let pct = CGFloat(i)/CGFloat(labels.count-1)
        let centerX = (view.bounds.size.width-2*thumbIndent) * pct + thumbIndent
        return [
            label.centerXAnchor.constraint(equalTo: slider.leftAnchor, constant: centerX),
            label.bottomAnchor.constraint(equalTo: slider.topAnchor, constant: 0),
        ]
        }.flatMap { $0 }
        .
        .
        .
}

【讨论】:

    猜你喜欢
    • 2010-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-04
    • 2021-04-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多