Here is an image of a simple APP I am trying to make

该应用程序具有用于中心紫色按钮的平移手势识别器,该按钮在移动时如果与四个橙色按钮中的任意一个相交,则该紫色按钮会进行动画处理并在与之交界的按钮范围内移动,否则会动画化回到初始起始位置即中心。

第一次平移紫色按钮时,按钮的框架会更新,但是如果第二次尝试,按钮的框架将保持不变(当它位于视图中心时的值)。

我猜想这是我缺少的与“自动版式”相关的内容,因为如果我取消了紫色中心按钮的约束,则每次平移时帧都会正确更新。

有人可以解释约束动画时我要记住的几点吗

这是我用于处理平移手势的代码:

@objc func handleCenterRectPan(_ pannedView: UIPanGestureRecognizer) {

        let fallBackAnimation = UIViewPropertyAnimator(duration: 0.3, dampingRatio: 0.5) {
                if self.button1.frame.intersects(self.centerRect.frame) {
                    self.centerRect.center = self.button1.center
                } else if self.button2.frame.contains(self.centerRect.frame) {
                    self.centerRect.center = self.button2.center
                } else if self.button3.frame.contains(self.centerRect.frame) {
                    self.centerRect.center = self.button3.center
                } else if self.button4.frame.contains(self.centerRect.frame) {
                    self.centerRect.center = self.button4.center
                } else {
                    // no intersection move to original position
                    self.centerRect.frame = OGValues.oGCenter
                }
        }

        switch pannedView.state {
        case .began:
            self.centerRect.center = pannedView.location(in: self.view)
        case .changed:
            print("Changed")
            self.centerRect.center = pannedView.location(in: self.view)
        case .ended, .cancelled, .failed :
            print("Ended")
            fallBackAnimation.startAnimation();
            //snapTheRectangle()
        default:
            break
        }
    }

最佳答案

首先,如果您的目标是平稳地移动视图,则不应施加任何限制。而且,如果您无法抗拒约束,那么必须继续更新约束而不是框架(中心),
在您的代码中,我假设您已经给了紫色按钮中心约束,然后随着用户使用平移手势拖动来更改按钮的中心。问题是给您的约束仍然处于活动状态,并且在布局需要更新时会尝试将其重新设置。

所以你可以做的是

不要给出限制,因为当用户拖动时它需要自由移动

要么

为约束创建IBoutlet,并在用户拖动时将.isActive设置为false,如果它不在其他任何按钮中,则将其设置为true,并更新UpdateLayoutIfNeeded,这样它将返回到原始位置。 (好的方法)

@IBOutlet var horizontalConstraints: NSLayoutConstraint!
@IBOutlet var verticalConstraints: NSLayoutConstraint!

//make active false as the user is dragging the view
horizontalConstraints.isActive = false
verticalConstraints.isActive = false
self.view.layoutIfNeeded()

//make it true again if its not inside any of the other views
horizontalConstraints.isActive = true
verticalConstraints.isActive = true
self.view.layoutIfNeeded()


要么

当用户移动视图时,更新constraints.constant以获取水平和垂直约束(这不是一个好的方法),如果不在其他任何视图内,请再次将其设为零

//make it true again if its not inside any of the other views
horizontalConstraints.constant = change in horizontal direction
verticalConstraints..constant =  change in vertical direction
self.view.layoutIfNeeded()


如您所说,编辑设置isActive = false后约束为零,因为
正如苹果博士所说,isActive实际要做的是添加和删除这些约束。


  激活或停用约束将在视图上调用addConstraint(:)和removeConstraint(:),该视图是此约束所管理的项目的最接近的共同祖先。使用此属性,而不是直接调用addConstraint(:)或removeConstraint(:)。


因此,使约束成为强引用确实可以解决问题,但我认为为IBOutelet设置强引用不是一个好主意,而以编程方式添加和删除约束则更好。查看此问题解除约束

关于ios - UIButton框架在平移时不会改变,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50579212/

10-13 03:57