【问题标题】:Adjust UIView frame on dragging拖动时调整 UIView 框架
【发布时间】:2015-11-07 10:28:11
【问题描述】:

我正在尝试在拖动时更改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 处变大。

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

所以问题是:

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

【问题讨论】:

    标签: ios swift uiview constraints touch-event


    【解决方案1】:

    您的视图快速增长的原因是您始终根据自第一次触地以来移动的距离更新当前视图高度。不要修改当前高度,您应该始终添加移动到视图原始高度的距离。

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

    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-从 Document Outline 中的高度约束拖动到 viewController。给它起一个名字,例如customViewHeight

    由于更新视图高度的代码位于视图代码本身中,因此请让 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
        }
    
    }
    

    【讨论】:

      【解决方案2】:

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

      基本上,使用自动布局的项目应避免使用框架更改视图。

      【讨论】:

        猜你喜欢
        • 2013-10-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-10-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多