ios - 如何获取 UIStackView 内的 UIView 的宽度值

标签 ios swift uistackview

我有自己的自定义 View ProgressBar,我以编程方式创建它:

let pb = ProgressBar(frame: CGRect(x: 0, y: 0, width: 200, height: 16))

我使用 200 的宽度创建它,但随后我将其添加到水平堆栈 View 中。因此, View 会根据屏幕尺寸增长,例如在 iPhone X 上会增长到 250。

在此自定义 View 中,我尝试使用宽度,但它始终为 200,并且会导致各种问题。

我真正需要的是 View 在堆栈 View 中的值,在我的例子中是 250。

有没有办法在我的自定义 View 中获取该值?
或者我有什么选择?

编辑 - 添加了一些代码:

class CustomTableViewCell: UITableViewCell {
  func configure() {
     let progressBar: ProgressBar = {
         let pb = ProgressBar(frame: CGRect(x: 0, y: 0, width: 200, height: 16))
     }()
  }
}

这段代码是从 View Controller 调用的:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if indexPath.row == 0 {
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell1") as! CustomTableViewCell
            cell.configure()
            return cell
}

编辑 2 - 自定义 View 代码:

class ProgressBar: UIView {

    var progressView: UIView = {
        let v = UIView()
        v.backgroundColor = .white
        return v
    }()

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

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

    func configure() {
        backgroundColor = UIColor(white: 1.0, alpha: 0.1)
        layer.cornerRadius = 8.0
        clipsToBounds = true

        progressView.frame = bounds
        progressView.frame.size.width = 0.0
        addSubview(progressView)
    }

    func animate(_ pct: CGFloat) -> Void {
        UIView.animate(withDuration: 1.0, animations: {
            self.progressView.frame.size.width = self.bounds.size.width * pct
        })
    }
}

edit3 - 调用动画

    let progressBar: ProgressBar = {
        let pb = ProgressBar(frame: CGRect(x: 0, y: 0, width: 200, height: 16))
        pb.translatesAutoresizingMaskIntoConstraints = false

        if data.count >= i {
            if let session = data[i - 1].session {
                let values = Array(session).sorted(by: { $0.date.compare($1.date) == .orderedDescending })
                var sum = 0.0
                for value in values {
                    sum += Double(value.score)
                }
                pb.animate(CGFloat(sum / 40)) // returns a value between 0 and 1
            }
        }

        return pb;
    }()

编辑 4:

enter image description here

编辑 5 - 添加调试约束:

Printing description of $16:
<UIView: 0x107d6a100; frame = (0 0; 200 16); layer = <CALayer: 0x1d003f3c0>>
Printing description of $17:
<StepUp.ProgressBar: 0x107d6c8e0; frame = (54.3333 0; 250 16); clipsToBounds = YES; layer = <CALayer: 0x1d0220880>>

最佳答案

正如我在评论部分提到的,将进度 View 放在堆栈 View 中并不是一个明智的想法,这将需要繁琐的步骤来实现 width。改变动画。

首先,您需要取消显式设置 frame即:在使用自动布局时不要指定宽度和高度。使用 CGRectZero相反。

然后您需要将堆栈 View (我假设您使用垂直堆栈 View )配置为:

stackView.alignment = .leading

您不能使用任何 fill类型在这里。因为如果你使用填充,那么所有排列的 subview 都应该具有堆栈 View 的整个宽度。因此,您将无法修改它们的任何宽度以使动画发生。

现在,只要您提供堆栈 View .leading对齐您的普通 View (没有固有内容大小的 View )将被赋予宽度 zero .因此,当您运行您的应用程序时,您将看不到任何 View 。在这里,您需要完成繁琐的工作,为它们中的每一个指定宽度。一种解决方案可能是:您枚举堆栈 View 的 subview ,并为所有 View 提供与堆栈 View 相同的宽度,使进度 View 的宽度为零

// update these when the sub views of the view are layout already
// otherwise stack view won't have it's own size yet 
stackView.subviews.forEach { (view) in
    if view == progressView {
        // save this constraint for use when animating
        progressViewWidthConstraint = view.widthAnchor.constraint(equalToConstant: 0)
        progressViewWidthConstraint.isActive = true
    } else {
        view.widthAnchor.constraint(equalToConstant: stackView.frame.size.width).isActive = true
    }
}

现在你的动画应该是:

view.layoutIfNeeded()
progressViewWidthConstraint.constant = stackView.frame.size.width
UIView.animate(withDuration: 2) {
    self.view.layoutIfNeeded()
}

结果如下: Animate UIView as progress view inside a UIStackView

我做了一个 demo如果您在此过程中遇到困难。干杯🍻

关于ios - 如何获取 UIStackView 内的 UIView 的宽度值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50667566/

相关文章:

ios - 当遇到 subview (UIStackView > ContainerView)时,UIScrollView 停止垂直滚动

ios - 在现有项目中添加 Storyboard 支持

ios - subview.origin 可以使用负坐标吗?

ios - iOS 应用程序中的生产崩溃日志

ios - ApplePay 'requiredShippingAddressFields' 在 iOS 11.0 中被弃用

ios - 无法从表格 View 中的所有自定义单元格收集数据

ios - 从 Storyboard 中撤消堆栈 View

iphone - 当uitextview使用google api加载当前位置时停止activityIndi​​cator

ios - 它在我的 Controller 中不显示 map (谷歌地图)。

ios - 如何让单个UIStackView的行高动态调整满屏?