Подпредставления не перемещаются с родительским UIView - PullRequest
1 голос
/ 28 мая 2020

Я пытаюсь создать приложение, основанное на редактировании изображений, и у меня возникают некоторые проблемы с кодированием изменения размера путем перетаскивания углов кадрирования.

У меня есть croppingView.swift , где прямоугольник обрезки рисуется при запуске:

override func viewDidAppear(_ animated: Bool) {
        let imagePoint = CGPoint(x: contentView.center.x, y: contentView.center.y)

        let imageSize = CGSize(width: cropImageView.image!.size.width, height: cropImageView.image!.size.height)
        let widthScale = cropImageView.frame.width / imageSize.width
        let heightScale = cropImageView.frame.height / imageSize.height
        let scale = min(widthScale, heightScale)
        let width = imageSize.width * scale
        let height = imageSize.height * scale
        let size = CGSize(width: width, height: height)

        let originViewFrame = CGPoint(x: imagePoint.x - width/2.0, y: imagePoint.y - height/2.0)

        let cropSize = CGSize(width: width * 0.7, height: height * 0.7)
        let cropViewFrame = CGRect(origin: originViewFrame, size: cropSize)

        cropView = ShapeView(frame: cropViewFrame)
        cropView.backgroundColor = UIColor(red: 224.0/255.0, green: 224.0/255.0, blue: 224.0/255.0, alpha: 0.3)
        cropView.layer.borderColor = UIColor(red: 97.0/255.0, green: 97.0/255.0, blue: 97.0/255.0, alpha: 1.0).cgColor
        cropView.layer.borderWidth = 1.0
        cropView.center = imagePoint
        self.view.addSubview(cropView)
}

ShapeView.swift для рисования области обрезки выглядит следующим образом:

class ShapeView: UIView {

    var previousLocation = CGPoint.zero

    var topLeft = DragHandle(fillColor:UIColor(red: 0.0/255.0, green: 150.0/255.0, blue: 136.0/255.0, alpha: 1.0),
                             strokeColor: UIColor.white)
    var topRight = DragHandle(fillColor:UIColor(red: 0.0/255.0, green: 150.0/255.0, blue: 136.0/255.0, alpha: 1.0),
                              strokeColor: UIColor.white)
    var bottomLeft = DragHandle(fillColor:UIColor(red: 0.0/255.0, green: 150.0/255.0, blue: 136.0/255.0, alpha: 1.0),
                                strokeColor: UIColor.white)
    var bottomRight = DragHandle(fillColor:UIColor(red: 0.0/255.0, green: 150.0/255.0, blue: 136.0/255.0, alpha: 1.0),
                                 strokeColor: UIColor.white)

    override func didMoveToSuperview() {
        superview?.addSubview(topLeft)
        superview?.addSubview(topRight)
        superview?.addSubview(bottomLeft)
        superview?.addSubview(bottomRight)

        var pan = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
        topLeft.addGestureRecognizer(pan)
        pan = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
        topRight.addGestureRecognizer(pan)
        pan = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
        bottomLeft.addGestureRecognizer(pan)
        pan = UIPanGestureRecognizer(target: self, action: #selector(handlePan))
        bottomRight.addGestureRecognizer(pan)
        pan = UIPanGestureRecognizer(target: self, action: #selector(handleMove))
        self.addGestureRecognizer(pan)

        self.updateDragHandles()
    }

    func updateDragHandles() {
        topLeft.center = self.transformedTopLeft()
        topRight.center = self.transformedTopRight()
        bottomLeft.center = self.transformedBottomLeft()
        bottomRight.center = self.transformedBottomRight()
    }

    //Gesture Methods
    @IBAction func handleMove(gesture:UIPanGestureRecognizer) {
        let translation = gesture.translation(in: self.superview!)
        var center = self.center
        center.x += translation.x
        center.y += translation.y
        self.center = center
        gesture.setTranslation(CGPoint.zero, in: self.superview!)
        updateDragHandles()
    }

    @IBAction func handlePan(gesture:UIPanGestureRecognizer) {
        let translation = gesture.translation(in: self)
        switch gesture.view! {
        case topLeft:
            if gesture.state == .began {
                self.setAnchorPoint(anchorPoint: CGPoint(x: 1, y: 1))
            }
            self.bounds.size.width -= translation.x
            self.bounds.size.height -= translation.y
        case topRight:
            if gesture.state == .began {
                self.setAnchorPoint(anchorPoint: CGPoint(x: 0, y: 1))
            }
            self.bounds.size.width += translation.x
            self.bounds.size.height -= translation.y

        case bottomLeft:
            if gesture.state == .began {
                self.setAnchorPoint(anchorPoint: CGPoint(x: 1, y: 0))
            }
            self.bounds.size.width -= translation.x
            self.bounds.size.height += translation.y
        case bottomRight:
            if gesture.state == .began {
                self.setAnchorPoint(anchorPoint: CGPoint.zero)
            }
            self.bounds.size.width += translation.x
            self.bounds.size.height += translation.y
        default:()
        }

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

Как вы можете видеть I ' m добавив по одному кружку в каждом углу прямоугольника. Эти круги используются для изменения размера области обрезки путем перетаскивания. Здесь ключом является функция updateDragHandles(), которая обновляет позиции всех остальных кругов, сохраняя их по углам.

Таким образом, при запуске область обрезки выглядит так:

enter image description here

И когда пользователь перемещает, например, правый нижний угол, перетаскивая, все работает нормально:

enter image description here

Теперь Проблема в том, что когда я нажимаю кнопку портретной ориентации, чтобы изменить ориентацию области обрезки. Со следующим кодом в croppingView.swift серый прямоугольник правильно меняет размер, но круги остаются на своем месте:

@IBAction func portButton(_ sender: Any) {
        portButton.tintColor = UIColor.systemBlue
        landButton.tintColor = UIColor.systemGray
        isPortait = 1
        let inWidth = cropView.frame.size.width
        let inHeight = cropView.frame.size.height
        if inWidth > inHeight {
            let scaleW = cropView.frame.size.height / cropView.frame.size.width
            let scaleH = cropView.frame.size.width / cropView.frame.size.height
            let fixPoint = CGPoint(x: 0.5, y: 0.5)
            cropView.setAnchorPoint(anchorPoint: fixPoint)
            cropView.transform = cropView.transform.scaledBy(x: scaleW, y: scaleH)
            let vc = ShapeView()
            vc.updateDragHandles()
        }
    }

Это похоже на то, что updateDragHandles не работает из этого ViewController .. .

enter image description here

Вероятно, это основная c ошибка, но я не могу найти решение.

Есть предложения?

Заранее спасибо!

DragHandle.swift

let diameter:CGFloat = 30

import UIKit

class DragHandle: UIView {

  var fillColor = UIColor.darkGray
  var strokeColor = UIColor.lightGray
  var strokeWidth: CGFloat = 1.0

  required init(coder aDecoder: NSCoder) {
    fatalError("Use init(fillColor:, strokeColor:)")
  }

  init(fillColor: UIColor, strokeColor: UIColor, strokeWidth width: CGFloat = 1.0) {
    super.init(frame: CGRect(x: 0, y: 0, width: diameter, height: diameter))
    self.fillColor = fillColor
    self.strokeColor = strokeColor
    self.strokeWidth = width
    self.backgroundColor = UIColor.clear
  }

    override func draw(_ rect: CGRect)
    {
        super.draw(rect)
        let handlePath = UIBezierPath(ovalIn: rect.insetBy(dx: 10 + strokeWidth, dy: 10 + strokeWidth))
        fillColor.setFill()
        handlePath.fill()
        strokeColor.setStroke()
        handlePath.lineWidth = strokeWidth
        handlePath.stroke()
    }
}

UIViewExtensions.swift

import Foundation
import UIKit

extension UIView {
    func offsetPointToParentCoordinates(point: CGPoint) -> CGPoint {
      return CGPoint(x: point.x + self.center.x, y: point.y + self.center.y)
    }

    func pointInViewCenterTerms(point:CGPoint) -> CGPoint {
      return CGPoint(x: point.x - self.center.x, y: point.y - self.center.y)
    }

    func pointInTransformedView(point: CGPoint) -> CGPoint {
      let offsetItem = self.pointInViewCenterTerms(point: point)
      let updatedItem = offsetItem.applying(self.transform)
      let finalItem = self.offsetPointToParentCoordinates(point: updatedItem)
      return finalItem
    }

    func originalFrame() -> CGRect {
      let currentTransform = self.transform
      self.transform = .identity
      let originalFrame = self.frame
      self.transform = currentTransform
      return originalFrame
    }

    func transformedTopLeft() -> CGPoint {
      let frame = self.originalFrame()
      let point = frame.origin
      return self.pointInTransformedView(point: point)
    }

    func transformedTopRight() -> CGPoint {
      let frame = self.originalFrame()
      var point = frame.origin
      point.x += frame.size.width
      return self.pointInTransformedView(point: point)
    }

    func transformedBottomRight() -> CGPoint {
      let frame = self.originalFrame()
      var point = frame.origin
      point.x += frame.size.width
      point.y += frame.size.height
      return self.pointInTransformedView(point: point)
    }

    func transformedBottomLeft() -> CGPoint {
      let frame = self.originalFrame()
      var point = frame.origin
      point.y += frame.size.height
      return self.pointInTransformedView(point: point)
    }

    func setAnchorPoint(anchorPoint: CGPoint) {
      var newPoint = CGPoint(x: self.bounds.size.width * anchorPoint.x, y: self.bounds.size.height * anchorPoint.y)
      var oldPoint = CGPoint(x: self.bounds.size.width * self.layer.anchorPoint.x, y: self.bounds.size.height * self.layer.anchorPoint.y)

      newPoint = newPoint.applying(self.transform)
      oldPoint = oldPoint.applying(self.transform)

      var position = self.layer.position
      position.x -= oldPoint.x
      position.x += newPoint.x
      position.y -= oldPoint.y
      position.y += newPoint.y

      self.layer.position = position
      self.layer.anchorPoint = anchorPoint
    }
}
...