我一直在做这个包含UIImageView的小应用程序。我可以点击它,图像的每个角上都会出现4个圆圈。我必须能够从角上拖动手指来调整图像的大小。但是调整大小不起作用。根据我的理解-我必须在 * touchesMoved * 方法中更新imageView的约束。
我用这个帖子作为参考:How to resize UIView by dragging from its edges?
设置图像视图、滚动视图和按钮
struct ResizeRect{
var topTouch = false
var leftTouch = false
var rightTouch = false
var bottomTouch = false
var middelTouch = false
}
这是我画在角落里的圆圈
private var topLeftCircleLayer: CAShapeLayer!
private var topRightCircleLayer: CAShapeLayer!
private var bottomLeftCircleLayer: CAShapeLayer!
private var bottomRightCircleLayer: CAShapeLayer!
imageView的约束
一个二个一个一个
设置我的视图
override func viewDidLoad() {
super.viewDidLoad()
scrollView.delegate = self
setupView()
addTapGestureRecognizer()
addPinchGestureRecognizer()
addRotateButton()
addDeletePhotoButton()
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
borderLayer.path = UIBezierPath(rect: imageView.bounds).cgPath
addConstraintsForItems()
createCircles()
}
private func addConstraintsForItems() {
imageViewTopConstraint = imageView.topAnchor.constraint(equalTo: view.topAnchor, constant: 180)
imageViewBottomConstraint = imageView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -180)
imageViewLeadingConstraint = imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 70)
imageViewTrailingConstraint = imageView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -70)
NSLayoutConstraint.activate([imageViewTopConstraint, imageViewBottomConstraint, imageViewLeadingConstraint, imageViewTrailingConstraint])
}
private func setupView() {
view.addSubview(scrollView)
view.addSubview(rotateButton)
view.addSubview(deleteButton)
scrollView.addSubview(imageView)
borderLayer.fillColor = UIColor.clear.cgColor
borderLayer.strokeColor = UIColor.black.cgColor
borderLayer.lineWidth = 2
borderLayer.isHidden = true
imageView.layer.addSublayer(borderLayer)
}
圆创建
private func updateCircles() {
let topLeft = CGPoint(x: imageView.frame.minX, y: imageView.frame.minY)
topLeftCircleLayer.position = topLeft
let topRight = CGPoint(x: imageView.frame.maxX, y: imageView.frame.minY)
topRightCircleLayer.position = topRight
let bottomLeft = CGPoint(x: imageView.frame.minX, y: imageView.frame.maxY)
bottomLeftCircleLayer.position = bottomLeft
let bottomRight = CGPoint(x: imageView.frame.maxX, y: imageView.frame.maxY)
bottomRightCircleLayer.position = bottomRight
imageView.layer.insertSublayer(topLeftCircleLayer, at: 0)
imageView.layer.insertSublayer(topRightCircleLayer, at: 1)
imageView.layer.insertSublayer(bottomLeftCircleLayer, at: 2)
imageView.layer.insertSublayer(bottomRightCircleLayer, at: 3)
}
private func createCircles() {
topLeftCircleLayer = createCircle(at: CGPoint(x: imageView.frame.minX, y: imageView.frame.minY))
topRightCircleLayer = createCircle(at: CGPoint(x: imageView.frame.maxX, y: imageView.frame.minY))
bottomLeftCircleLayer = createCircle(at: CGPoint(x: imageView.frame.minX, y: imageView.frame.maxY))
bottomRightCircleLayer = createCircle(at: CGPoint(x: imageView.frame.maxX, y: imageView.frame.maxY))
}
private func createCircle(at position: CGPoint) -> CAShapeLayer {
let circle = CAShapeLayer()
circle.path = UIBezierPath(arcCenter: position, radius: 10, startAngle: 0, endAngle: .pi * 2, clockwise: true).cgPath
circle.fillColor = UIColor.systemPink.cgColor
circle.strokeColor = UIColor.white.cgColor
circle.lineWidth = 6
circle.isHidden = !isCirclesVisible
imageView.layer.addSublayer(circle)
return circle
}
- 这是最重要的一步,我试着把角落拉起来**
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first{
let touchStart = touch.location(in: self.view)
print(touchStart)
resizeRect.topTouch = false
resizeRect.leftTouch = false
resizeRect.rightTouch = false
resizeRect.bottomTouch = false
if touchStart.y > imageView.frame.maxY - proxyFactor && touchStart.y < imageView.frame.maxY + proxyFactor {
resizeRect.bottomTouch = true
print("bottom")
}
if touchStart.x > imageView.frame.maxX - proxyFactor && touchStart.x < imageView.frame.maxX + proxyFactor {
resizeRect.rightTouch = true
print("right")
}
if touchStart.x > imageView.frame.minX - proxyFactor && touchStart.x < imageView.frame.minX + proxyFactor {
resizeRect.leftTouch = true
print("left")
}
if touchStart.y > imageView.frame.minY - proxyFactor && touchStart.y < imageView.frame.minY + proxyFactor {
resizeRect.topTouch = true
print("top")
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first{
let currentTouchPoint = touch.location(in: self.view)
let previousTouchPoint = touch.previousLocation(in: self.view)
let deltaX = currentTouchPoint.x - previousTouchPoint.x
let deltaY = currentTouchPoint.y - previousTouchPoint.y
if resizeRect.topTouch && resizeRect.leftTouch {
if imageViewTopConstraint.constant + deltaY > 0 && imageViewLeadingConstraint.constant + deltaX > 0 {
imageViewTopConstraint.constant += deltaY
imageViewLeadingConstraint.constant += deltaX
}
}
if resizeRect.topTouch && resizeRect.rightTouch {
if imageViewTopConstraint.constant + deltaY > 0 && imageViewTrailingConstraint.constant - deltaX > 0 {
imageViewTopConstraint.constant += deltaY
imageViewTrailingConstraint.constant -= deltaX
}
}
if resizeRect.bottomTouch && resizeRect.leftTouch {
if imageViewBottomConstraint.constant - deltaY > 0 && imageViewLeadingConstraint.constant + deltaX > 0 {
imageViewLeadingConstraint.constant += deltaX
imageViewBottomConstraint.constant -= deltaY
}
}
if resizeRect.bottomTouch && resizeRect.rightTouch {
if imageViewBottomConstraint.constant - deltaY > 0 && imageViewTrailingConstraint.constant - deltaX > 0 {
imageViewTrailingConstraint.constant -= deltaX
imageViewBottomConstraint.constant -= deltaY
}
}
UIView.animate(withDuration: 0.25, delay: 0, options: UIView.AnimationOptions.curveEaseIn) {
self.view.layoutIfNeeded()
}
}
}
编辑1:我对代码做了一些更新。我的应用程序终于能理解我触摸imageView的时候了,当我触摸一个角的时候,它能告诉我哪个角被触摸了,但是调整大小的功能不太好。有时候它能正常工作,但是调整大小的速度非常慢。在控制台里,它说我有这个错误:
Probably at least one of the constraints in the following list is one you don't want.
Try this:
(1) look at each constraint and try to figure out which you don't expect;
(2) find the code that added the unwanted constraint or constraints and fix it.
(
"<NSLayoutConstraint:0x600000cf8910 H:|-(65)-[UIImageView:0x13a707300] (active, names: '|':UIView:0x13c20f220 )>",
"<NSLayoutConstraint:0x600000ce0640 H:|-(70)-[UIImageView:0x13a707300] (active, names: '|':UIView:0x13c20f220 )>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x600000ce0640 H:|-(70)-[UIImageView:0x13a707300] (active, names: '|':UIView:0x13c20f220 )>
我尝试更新约束,但由于某种原因,它不允许我更新。我克隆了github project from a person that wrote a solution。他为约束创建了IBOutlets,据我所知,从IBOutlets创建的约束与我拥有的约束有某种不同。我如何解决约束问题?如果有人能注意到我的圆创建有什么问题,我将非常感激。现在我只看到图像中间下方的1 ...
1条答案
按热度按时间n9vozmp41#
你的方法有几个问题...
首先,这些都不是:
viewDidLayoutSubviews()
被调用了不止一次,如果你正在改变视图/约束,它将被调用很多次。第二,您可能在使用代码设置(与使用
@IBOutlet
连接的Storyboard设置相反)时遇到麻烦,因为约束的顺序颠倒了。在您的代码中,您设置了imageView上的所有4个约束,从
imageView -> view
开始。第三,您正在某些需要使用
.bounds
的地方使用.frame
。下面是你的代码的修改版本。我不知道你是如何决定何时显示/隐藏角圆的,所以我添加了一个双击手势来激活/关闭“调整大小”模式:
当你运行它的时候,你会注意到在拖动和调整大小的时候有一些“滞后”--参见代码中的注解。
类似的方法可能会发现它响应更快,而且更易于管理...
我们不添加“圆形图层”,而是添加“圆形视图”作为图像视图的子视图,然后我们可以设置图像视图角的约束,让自动布局处理所有的定位。
代码更少...利用自动布局...响应更快...
先运行上面的版本,然后给予这个: