在拖动时调整UIView框架

时间:2015-11-07 10:28:12

标签: ios swift uiview constraints touch-event

我正在尝试在拖动时更改UIView框架。我将UIView子类化,并编写了touchesBegantouchesMoved方法。他们在这里:

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    let touch = touches.first
    startPosition = touch?.locationInView(self)
}

override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
    let touch = touches.first
    let endPosition = touch?.locationInView(self)
    let difference = endPosition!.y - startPosition.y
    let newFrame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.width, self.frame.height + difference)
    self.frame = newFrame
}

但结果我得到了意想不到的行为。描述它有点难。 Here's video how it works.。小阻力(大约20px)使得框架在大约100px上变大。

我的自定义视图也有一些限制。自定义视图底部的图像应该始终存在:

enter image description here

所以问题是:

  1. 如何在距离用户拖动时使视图更大。
  2. 为什么在更改框架后不再应用约束以及如何再次应用它们?

2 个答案:

答案 0 :(得分:4)

您的视图快速增长的原因是您始终使用自首次触摸后移动的距离更新当前视图高度。您应该始终添加移动到视图原始高度的距离,而不是修改当前高度。

将另一个属性添加到自定义视图以跟踪视图的原始高度。将其设置为touchesBegan,然后在originalHeight中计算框架时使用touchesMoved

class CustomView: UIView {

    var startPosition: CGPoint?
    var originalHeight: CGFloat = 0

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        let touch = touches.first
        startPosition = touch?.locationInView(self)
        originalHeight = self.frame.height
    }

    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
        let touch = touches.first
        let endPosition = touch?.locationInView(self)
        let difference = endPosition!.y - startPosition!.y
        let newFrame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.width, originalHeight + difference)
        self.frame = newFrame
    }

}
  

在更改框架和如何应用后,为什么限制不适用   他们又来了?

使用自动布局时,你真的不应该更新帧。正确的方法是在视图的高度约束中添加@IBOutlet,然后在希望更改视图高度时更新约束的constant属性。

执行此操作时,自动布局将使用更新的高度正确定位自定义视图的子视图。

要向代码的高度约束添加@IBOutlet Control -drag,从文档大纲中的高度约束到您的viewController。为其命名,例如customViewHeight

Control drag to create @IBOutlet for height constraint

由于用于更新视图高度的代码位于视图代码本身中,因此请让viewController将高度约束分配给viewDidLoad中的自定义视图。然后,自定义视图可以更新高度约束的constant属性以调整视图大小。

class ViewController: UIViewController {

    @IBOutlet weak var customViewHeight: NSLayoutConstraint!

    @IBOutlet weak var customView: CustomView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Assign the layout constraint to the custom view so that it can update it itself
        customView.customViewHeight = customViewHeight
    }
}

class CustomView: UIView {

    var startPosition: CGPoint?
    var originalHeight: CGFloat = 0
    var customViewHeight: NSLayoutConstraint!

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        let touch = touches.first
        startPosition = touch?.locationInView(self)
        originalHeight = customViewHeight.constant
    }

    override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
        let touch = touches.first
        let endPosition = touch?.locationInView(self)
        let difference = endPosition!.y - startPosition!.y
        customViewHeight.constant = originalHeight + difference
    }

}

答案 1 :(得分:0)

在您的情况下,我认为您应该更改底部约束的常量,而不是更改视图的框架。顺便说一句,您最好使用手势而不是覆盖触摸方法,因为手势是更高级别的API并且更易于维护

基本上,使用Autolayout的项目应避免使用框架更改视图。