【问题标题】:Changing UIView rotation will change it's frame size. How to keep frame size after rotating?改变 UIView 旋转将改变它的帧大小。旋转后如何保持帧大小?
【发布时间】:2018-08-12 10:43:19
【问题描述】:

我正在通过UIRotationGestureRecognizer 旋转UIView,但我有一个问题,旋转后的UIView 的帧大小将在旋转时改变。

targetView = UIView(frame: CGRect(x: self.view.center.x, y: self.view.center.y , width: 100, height: 100))
targetView.backgroundColor = .red
targetView.isUserInteractionEnabled = true
self.view.addSubview(targetView)

targetView.center = self.view.center

let rotate = UIRotationGestureRecognizer(target: self, action: #selector(rotatedView))
targetView.addGestureRecognizer(rotate)

这里是旋转功能:

@objc func rotatedView(_ sender: UIRotationGestureRecognizer) {
var originalRotation = CGFloat()
if sender.state == .began {
    sender.rotation = lastRotation 
    originalRotation = sender.rotation

    print("TargetView Frame Size: [START ROTATE] ", self.targetView.frame.size)
    print("TargetView Bounse Size: [START ROTATE] ", self.targetView.bounds)

} else if sender.state == .changed {
    let newRotation = sender.rotation + originalRotation
    sender.view?.transform = CGAffineTransform(rotationAngle: newRotation)

    print("TargetView Frame Size: [ROTATETING] ", self.targetView.frame.size)
    print("TargetView Bounse Size: [ROTATING ROTATE] ", self.targetView.bounds)
    }
}

大小会改变:

TargetView Frame Size: [START ROTATE]  (100.0, 100.0)
TargetView Frame Size: [ROTATETING]  (110.564206726133, 110.564206726133)

如何像开始旋转一样在旋转后保持帧大小?!

编辑:

我有这些手势:旋转、调整大小、移动。

移动运行良好,但旋转正在改变大小。我可以在这里使用边界,但如果我也调整大小,边界就不再有用了。

【问题讨论】:

  • 是的,框架大小增加了,因为框架是包含所有内容的矩形,并且旋转的正方形比未旋转的正方形更宽更高。界限没有改变。为什么会出现这个问题?
  • @vacawama 因为我必须保存旋转和缩放的 UIView 大小和位置,并在以后生成相同的 UIView。我可以使用边界,但我也想添加缩放功能,并且在缩放时边界不会改变。 :-|
  • 你能保存transform吗?那和view 应该是您以后重新创建它所需的一切。
  • 我必须将旋转和大小转换为一般度量,并将主题发送到服务器,以便在其他设备(Android、电视、Web 等)上呈现它。问题是:旋转会改变帧大小。我也必须发送尺寸。 (已编辑)
  • 其他设备需要什么规格?听起来您需要原始视图的大小、旋转角度和比例。

标签: swift uiview core-graphics


【解决方案1】:

您需要缩放但未旋转的视图大小。您可以从视图的bounds.sizetransform 计算得出。

示例

let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 150))

// Scale view by 3X horizontally and by 4X vertically and
// rotate by 45 degrees
view.transform = CGAffineTransform(scaleX: 3, y: 4).rotated(by: 45.0 / 180.0 * .pi)

let transform = view.transform

// Find the angle, print it in degrees
let angle = atan2(-transform.c, transform.a)
print(angle * 180.0 / .pi) // 44.99999999999999

// Find scaleX and scaleY
let scaleX = transform.a * cos(angle) - transform.c * sin(angle)
let scaleY = transform.d * cos(angle) + transform.b * sin(angle)
print(scaleX) // 3.0
print(scaleY) // 4.0

print(view.frame.size)  // (530.3300858899106, 707.1067811865476)
print(view.bounds.size) // (100.0, 150.0)

let adjustedSize = CGSize(width: view.bounds.size.width * scaleX, height: view.bounds.size.height * scaleY)

// print non-rotated but scaled size
print(adjustedSize) // (300.0, 600.0)

这是一个方便的扩展,适用于缩放、旋转和平移(移动)的视图:

extension CGAffineTransform {
    var angle: CGFloat { return atan2(-self.c, self.a) }

    var angleInDegrees: CGFloat { return self.angle * 180 / .pi }

    var scaleX: CGFloat {
        let angle = self.angle
        return self.a * cos(angle) - self.c * sin(angle)
    }

    var scaleY: CGFloat {
        let angle = self.angle
        return self.d * cos(angle) + self.b * sin(angle)
    }
}

现在,如果你有一个 UIView:

let angle = view.transform.angleInDegrees
let scaleX = view.transform.scaleX
let scaleY = view.transform.scaleY
let adjustedSize = CGSize(width: view.bounds.size.width * scaleX, height: view.bounds.size.height * scaleY)

【讨论】:

  • 谢谢,太棒了。我在数学上完全是菜鸟。 :D
猜你喜欢
  • 1970-01-01
  • 2012-05-01
  • 2022-06-13
  • 2019-12-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-17
相关资源
最近更新 更多