我制作了一个自定义视图,可以通过拖动一个圆角按钮来调整大小和旋转。
我需要视图才能拖动来改变它的位置。
我尝试了几种方法,但没有一种方法属性(视图在组合旋转和调整大小动作时只是奇怪的行为)。
这样做的正确方法是什么?
根据这个答案引用苹果公司的文件What to use to move UIView self.frame or self.transform property? 我不应该使用frame属性和转换,所以我假设我需要使用CGAffineTransform来改变视图的位置? (我试过这个,但效果不好)
import Foundation
import UIKit
class ResizeRotateView: UIImageView, Resizable {
private let buttonWidth: CGFloat = 40
private var themeColor: UIColor = UIColor.magentaColor()
// Rotation Resize
var radian: CGFloat = 0
private var tempAnglePanStart : Float = 0
private var tempAngleLastPanEnd: Float = 0
// UI Subviews
lazy var cornerButton: UIView = {
let b = UIView()
b.layer.cornerRadius = self.buttonWidth / 2
b.layer.borderWidth = 1
b.layer.borderColor = self.themeColor.CGColor
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(buttonTouchMoved) )
b.addGestureRecognizer(panGesture)
return b
}()
// Init
override init(frame: CGRect) {
super.init(frame: frame)
setupSuviews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupSuviews() {
addSubview( cornerButton )
addConstraintsWithFormat("H:[v0(\(buttonWidth))]", views: cornerButton)
addConstraintsWithFormat("V:[v0(\(buttonWidth))]", views: cornerButton)
addConstraint(NSLayoutConstraint(item: cornerButton, attribute: .CenterX, relatedBy: .Equal, toItem: self, attribute: .Right, multiplier: 1, constant: 0))
addConstraint(NSLayoutConstraint(item: cornerButton, attribute: .CenterY, relatedBy: .Equal, toItem: self, attribute: .Top, multiplier: 1, constant: 0))
}
override func hitTest(point: CGPoint, withEvent e: UIEvent?) -> UIView? { // This will enable gesture out of self.view's boundary. From stackoverflow.
if let result = super.hitTest(point, withEvent:e) {
return result
}
for sub in self.subviews.reverse() {
let pt = self.convertPoint(point, toView:sub)
if let result = sub.hitTest(pt, withEvent:e) {
return result
}
}
return nil
}
////// Event
func buttonTouchMoved(gestureRecognizer: UIPanGestureRecognizer) {
resize(gestureRecognizer)
rotate(gestureRecognizer)
}
////// Action
// Resize
func resize(gestureRecognizer: UIPanGestureRecognizer) {
// Temporary set aglet to 0
self.transform = CGAffineTransformMakeRotation( 0 )
// Resize
let locationInSelf = gestureRecognizer.locationInView(self)
resizeByKeepingAspectRatioByDistanceFromCenter(toLocation: locationInSelf)
layoutSubviews()
// Recover angle
self.transform = CGAffineTransformMakeRotation( radian )
layoutSubviews()
}
// Rotation
func rotate(gestureRecognizer: UIPanGestureRecognizer) {
guard let superView = self.superview else {
print("#Error: Super View not found")
return
}
let angle = self.angle(byLocation: gestureRecognizer.locationInView( superView ) )
if gestureRecognizer.state == .Began {
print("Pan begin:\(angle)")
tempAnglePanStart = angle - tempAngleLastPanEnd
}
let destinationAngle = angle - tempAnglePanStart
self.transform = CGAffineTransformMakeRotation( destinationAngle.degreesToRadians )
if gestureRecognizer.state == .Ended {
print("Pan ended")
tempAngleLastPanEnd = destinationAngle
}
}
////// Helper
func angle( firstPoint: CGPoint, secondPoint: CGPoint ) -> Float {
let dx = firstPoint.x - secondPoint.x
let dy = firstPoint.y - secondPoint.y
let angle = atan2(dy, dx).radiansToDegrees
let angleInFloat = Float( angle.double )
let formattedAngle = angleInFloat < 0 ? angleInFloat + 360.0 : angleInFloat
return formattedAngle
}
func angle(byLocation location: CGPoint) -> Float {
let targetViewCnter = self.center
return self.angle(targetViewCnter, secondPoint: location)
}
func setAngle(angle: Float) {
let radian = angle.degreesToRadians
self.transform = CGAffineTransformMakeRotation( radian )
self.radian = radian
}
}
我非常接近。我可以通过保持旋转角度和视图的大小来移动。剩下的问题是当我开始拖动时视图跳转了一点。
import Foundation
import UIKit
class ResizeRorateMovableView: ResizeRotateView {
var startCenter: CGPoint = CGPointZero
override init(frame: CGRect) {
super.init(frame: frame)
setupSuviews()
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(panGestureEvent))
addGestureRecognizer( panGesture )
userInteractionEnabled = true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func panGestureEvent(panGesture: UIPanGestureRecognizer) {
if panGesture.state == .Began {
self.startCenter = self.center
return
}
if panGesture.state == .Changed {
let location = panGesture.translationInView(self)
// Rotate first, then move
var transfrom = CGAffineTransformMakeRotation( self.radian )
transfrom = CGAffineTransformTranslate(transfrom, location.x, location.y)
self.transform = transfrom
return
}
}
}