【问题标题】:Resizing UIView using CGAffineTransform scale doesn't update frame使用 CGAffineTransform 缩放调整 UIView 的大小不会更新框架
【发布时间】:2022-06-16 14:07:37
【问题描述】:

我正在尝试使用 CGAffineTransform 比例调整包含几个子视图的 UIView(父)的大小。 我通过使用平移手势从一个角落拖动父级来调整父级的大小。 调整大小按预期工作,但如果我再次尝试调整大小,它会跳回初始帧。就好像它从来不知道它被调整了大小。

这些是我目前正在做的步骤:

1.- 就在平移手势开始时,我在超级视图中获得初始帧和触摸位置:

if gesture.state == .began {
        
        //We get all initial values from the first touch
        initialFrame = self.frame;
        touchStart = gesture.location(in: superview)
    }

2.- 然后我转到要拖动的手柄(在本例中为右上角),设置锚点,计算增量(初始触摸 - 移动的手势距离),计算新帧、缩放并应用变换。

    case topRight:
        
        if gesture.state == .began {
            self.setAnchorPoint(anchorPoint: CGPoint(x: 0, y: 1))
        }

        
        let deltaX = -1 * (touchStart.x - gesture.location(in: superview).x)
        let deltaY = 1 * (touchStart.y - gesture.location(in: superview).y)
        
        let newWidth = initialFrame.width + deltaX;
        let newHeight = initialFrame.height + deltaY;
        
        let scaleX:CGFloat = newWidth / initialFrame.width;
        let scaleY:CGFloat = newHeight / initialFrame.height;

        self.transform = CGAffineTransform.identity.scaledBy(x: scaleX, y: scaleY)

3.- 最后我将锚点重置到 UIView 的中间。

        if gesture.state == .ended {
            self.setAnchorPoint(anchorPoint: CGPoint(x: 0.5, y: 0.5))
         
 
        }

我附上了一个 gif,您可以在其中看到 UIView 从右上角的句柄调整大小。当我再次尝试调整它的大小时,它会跳回初始帧。 (好像视频重启了,不过这是跳转)

我错过了什么?我需要更新其他东西吗? 谢谢大家!

【问题讨论】:

  • 因为您将变换应用到初始帧,它永远不会改变。
  • 如果你能发布一些非常有用的代码@matt 谢谢。

标签: ios swift uiview cgaffinetransform cgaffinetransformscale


【解决方案1】:

所以答案其实很简单,下面这行代码是错误的:

self.transform = CGAffineTransform.identity.scaledBy(x: scaleX, y: scaleY)

这里我将缩放应用于恒等变换,它始终是原始大小。

只需将其更改为:

self.transform = self.initialTransform.scaledBy(x: scaleX, y: scaleY)

现在我将缩放应用到当前变换,该变换总是在手势开始时保存。

@objc func handleUserPan(gesture:UIPanGestureRecognizer) {
        
        if gesture.state == .began {
            

            self.initialTransform = self.transform;
            self.touchStart = gesture.location(in: resizableSelf.superview);
        }
        
        switch gesture.view! {
        case self.topRight: //This is just the circle view

            if gesture.state == .began {
                self..setAnchorPoint(anchorPoint: CGPoint(x: 1, y: 1))
            }
            
            
            let deltaX = 1 * (self.touchStart.x - gesture.location(in: superview).x)
            let deltaY = 1 * (self.touchStart.y - gesture.location(in: superview).y)
            
            let newWidth = self.initialFrame.width + deltaX;
            let newHeight = self.initialFrame.height + deltaY;
            
            let scaleX:CGFloat = newWidth / self.initialFrame.width;
            let scaleY:CGFloat = newHeight / self.initialFrame.height;

            self.transform = self.initialTransform.scaledBy(x: scaleX, y: scaleY)
            
        }
        default:()
        }

        gesture.setTranslation(CGPoint.zero, in: self)
        self.updateDragHandles()


        if gesture.state == .ended {
            self.setAnchorPoint(anchorPoint: CGPoint(x: 0.5, y: 0.5))
        }
    }

希望这对那些想要像 Photoshop 那样缩放 UIView 的人有所帮助。如果子视图被旋转,它甚至可以工作。

请记住,一旦视图被转换,您就不能再设置框架值。这就是为什么将所有视图都放在 superView 中会更方便,因此它可以处理所有大小调整。

目标是复制 Photoshop 在调整图层大小时所做的相同行为。

【讨论】:

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