Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 更新约束子视图时UIScrollView行为异常_Ios_Swift_Uiscrollview_Xib - Fatal编程技术网

Ios 更新约束子视图时UIScrollView行为异常

Ios 更新约束子视图时UIScrollView行为异常,ios,swift,uiscrollview,xib,Ios,Swift,Uiscrollview,Xib,我在XIB中制作了一个UIScrollView,用于我的入职培训。UIScrollView有3个入职视图。长话短说: 这很好用。但是,当第三页/最后一页在屏幕上时,我希望左上和右上的按钮(Overslaan-Volgende)在屏幕上/下设置动画。当我设置按钮的动画时,我的UIScrollView开始表现出奇怪的行为: 这是我使用的代码: func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity veloc

我在XIB中制作了一个
UIScrollView
,用于我的入职培训。
UIScrollView
有3个入职视图。长话短说:

这很好用。但是,当第三页/最后一页在屏幕上时,我希望左上和右上的按钮(Overslaan-Volgende)在屏幕上/下设置动画。当我设置按钮的动画时,我的UIScrollView开始表现出奇怪的行为:

这是我使用的代码:

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {

        let pageIndex = Int(targetContentOffset.pointee.x / self.frame.width)
        pageControl.currentPage = pageIndex

        if stepViews[pageIndex] is OnboardingLoginView {
            moveControlConstraintsOffScreen()
        } else {
            moveControlConstraintsOnScreen()
        }

        UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
            self.layoutIfNeeded()
        }, completion: nil)
    }
func-scrollViewWillendDraging(scrollView:UIScrollView,withVelocity:CGPoint,targetContentOffset:UnsafemeutablePointer){
让pageIndex=Int(targetContentOffset.pointee.x/self.frame.width)
pageControl.currentPage=pageIndex
如果stepViews[pageIndex]正在登录LoginView{
moveControlConstraintsOffScreen()
}否则{
MoveControlConstraintsOn屏幕()
}
UIView.animate(持续时间:0.5,延迟:0,使用SpringWithDamping:1,初始SpringVelocity:1,选项:.curveEaseOut,动画:{
self.layoutifneed()
},完成日期:无)
}

我调试了代码,结果表明,无论动画块如何,为约束设置新常量都会导致问题。如何使按钮在屏幕上向上/向外移动而不使我的scrollView行为怪异?

触发布局过程似乎会干扰您的scroll view定位。您可以实现
func-scrollViewDidScroll(\uScrollView:UIScrollView)
,并尝试按帧更新按钮视图,而无需更改自动布局约束。对于自动布局之外的帧更改,我通常使用
transform
属性,因为对
frame
bounds
的任何更改都会在下一个布局过程中被覆盖

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    guard mustBeOnLastPage else {
        buttonOne.tranform = .identity
        buttonTwo.tranform = .identity
        return
    }

    let offset = scrollView.contentOffset.x
    buttonOne.tranform = .init(translationX: 0, y: offset)
    buttonTwo.tranform = .init(translationX: 0, y: offset)
}
旧答案

这种解释与你的要求有点相切

因为看起来您正在分页上下文中使用滚动视图,所以我将使用UIPageViewController来解决这个问题。由于UIPageViewController在内部使用UIScrollView,因此可以观察滚动视图中最后一个视图的contentOffset来确定页面的滚动距离。 是的,这涉及到查看视图层次结构内部,但苹果已经五年没有改变它了,所以你应该是安全的。巧合的是,我上周实际实施了这种方法,它的效果非常好。
如果你感兴趣,我可以进一步扩展这个话题。可以找到为我指出正确方向的帖子。

触发布局过程似乎干扰了您的滚动视图定位。您可以实现
func-scrollViewDidScroll(\uScrollView:UIScrollView)
,并尝试按帧更新按钮视图,而无需更改自动布局约束。对于自动布局之外的帧更改,我通常使用
transform
属性,因为对
frame
bounds
的任何更改都会在下一个布局过程中被覆盖

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    guard mustBeOnLastPage else {
        buttonOne.tranform = .identity
        buttonTwo.tranform = .identity
        return
    }

    let offset = scrollView.contentOffset.x
    buttonOne.tranform = .init(translationX: 0, y: offset)
    buttonTwo.tranform = .init(translationX: 0, y: offset)
}
旧答案

这种解释与你的要求有点相切

因为看起来您正在分页上下文中使用滚动视图,所以我将使用UIPageViewController来解决这个问题。由于UIPageViewController在内部使用UIScrollView,因此可以观察滚动视图中最后一个视图的contentOffset来确定页面的滚动距离。 是的,这涉及到查看视图层次结构内部,但苹果已经五年没有改变它了,所以你应该是安全的。巧合的是,我上周实际实施了这种方法,它的效果非常好。 如果你感兴趣,我可以进一步扩展这个话题。可以找到为我指明正确方向的帖子。

我就是这么做的

我不能发布图片,你可以看看这个

这就是代码

var centerYConstraint: Constraint!

func setupConstraint() {
    fadeView.snp.makeConstraints { make in
        make.centerX.equalToSuperview()
        centerYConstraint = make.centerY.equalToSuperview().constraint
        make.size.equalTo(CGSize(width: 50, height: 50))
    }
}

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint,targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    let pageIndex = Int(targetContentOffset.pointee.x / self.view.frame.width)
    if pageIndex != 1 {
        centerYConstraint.update(offset: self.view.frame.height)
    } else {
        centerYConstraint.update(offset: 0)
    }

    UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: { 
        self.view.layoutIfNeeded()
    }, completion: nil)
}
var centerYConstraint:约束!
func setupConstraint(){
fadeView.snp.makeConstraints{make in
make.centerX.equalToSuperview()
centerYConstraint=make.centerY.equalToSuperview().constraint
制造尺寸相等(CGSize(宽:50,高:50))
}
}
func ScrollViewWillendDraging(scrollView:UIScrollView,withVelocity:CGPoint,targetContentOffset:UnsafemeutablePointer){
让pageIndex=Int(targetContentOffset.pointee.x/self.view.frame.width)
如果pageIndex!=1{
centerYConstraint.update(偏移量:self.view.frame.height)
}否则{
centerYConstraint.update(偏移量:0)
}
UIView.animate(持续时间:0.5,延迟:0,使用SpringWithDamping:1,初始SpringVelocity:1,选项:.curveEaseOut,动画:{
self.view.layoutifneed()
},完成日期:无)
}
以下是我的工作

我不能发布图片,你可以看看这个

这就是代码

var centerYConstraint: Constraint!

func setupConstraint() {
    fadeView.snp.makeConstraints { make in
        make.centerX.equalToSuperview()
        centerYConstraint = make.centerY.equalToSuperview().constraint
        make.size.equalTo(CGSize(width: 50, height: 50))
    }
}

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint,targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    let pageIndex = Int(targetContentOffset.pointee.x / self.view.frame.width)
    if pageIndex != 1 {
        centerYConstraint.update(offset: self.view.frame.height)
    } else {
        centerYConstraint.update(offset: 0)
    }

    UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: { 
        self.view.layoutIfNeeded()
    }, completion: nil)
}
var centerYConstraint:约束!
func setupConstraint(){
fadeView.snp.makeConstraints{make in
make.centerX.equalToSuperview()
centerYConstraint=make.centerY.equalToSuperview().constraint
制造尺寸相等(CGSize(宽:50,高:50))
}
}
func ScrollViewWillendDraging(scrollView:UIScrollView,withVelocity:CGPoint,targetContentOffset:UnsafemeutablePointer){
让pageIndex=Int(targetContentOffset.pointee.x/self.view.frame.width)
如果pageIndex!=1{
centerYConstraint.update(偏移量:self.view.frame.height)
}否则{
centerYConstraint.update(偏移量:0)
}
UIView.animate(持续时间:0.5,延迟:0,使用SpringWithDamping:1,初始SpringVelocity:1,选项:.curveEaseOut,动画:{
self.view.layoutifneed()
},完成日期:无)
}

根据@cloveleddy的回答,我做了两项修改:

1:看来layoutSubviews应该对这种奇怪的行为负责。要解决此问题,我阻止scrollView始终调用LayoutSubview:

override func layoutSubviews() {
    super.layoutSubviews()

    if !didLayoutSubviews {
        for index in 0..<stepViews.count {
            let page: UIView = stepViews[index]

            let xPosition = scrollView.frame.width * CGFloat(index)

            page.frame = CGRect(x: xPosition, y: 0, width: scrollView.bounds.width, height: scrollView.frame.height)

            scrollView.contentSize.width = scrollView.frame.width * CGFloat(index + 1)
        }

        didLayoutSubviews = true
    }
}
基于