通过点击创建 UIView 时如何不让它们重叠?

How do I not let UIViews overlap when I create them by tapping?

我正在创建一个日历应用程序,我点击以在 UIScrollView 中创建新事件。可以把它想象成苹果日历的“日视图”,您可以在其中创建新事件并在滚动视图的列表中查看它们。每个事件都是一个带有 TextField 的 UIView,现在一切正常,但我不确定如何做到这一点,以便在创建事件时事件不会重叠。

有什么方法可以防止 UIView 在创建或移动时重叠?我只是将它们向上或向下移动,所以我只需要防止它们在 y 轴上重叠。现在我点击创建它们,但它们可以重叠。有没有办法把它们放在同一个平面上,这样它们就不能叠加在一起?

强烈建议您 post 您自己的代码,以便我们了解您的大体方向。否则,我们双方的努力都会白费。

例如,您提到“现在一切正常”,但我不知道您是如何以垂直方式移动视图的。我继续对手势识别器进行子类化,希望它适合您的代码流程。

import UIKit.UIGestureRecognizerSubclass

class ViewController: UIViewController {
    let size = CGSize(width: 200, height: 100)
    var v1: UIView!
    var v2: UIView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.v1 = UIView(frame: .init(origin: .init(x: 100, y: 100), size: size))
        self.view.addSubview(self.v1)
        self.v1.backgroundColor = .orange
        self.v2 = UIView(frame: .init(origin: .init(x: 100, y: 300), size: size))
        self.view.addSubview(v2)
        self.view.addSubview(self.v2)
        self.v2.backgroundColor = .purple
        
        let verticalGesture = VerticalGesture(target: self, action: #selector(dragged))
        self.v2.addGestureRecognizer(verticalGesture)
    }
    
    @objc func dragged(_ sender: VerticalGesture) {
        
    }
}

class VerticalGesture: UIPanGestureRecognizer {
    private var touch: UITouch!
    private var currentView: UIView!
    private var currentSuperview: UIView!
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
        guard let firstTouch = touches.first, let currentView = self.view, let currentSuperview = currentView.superview else { return }
        self.touch = firstTouch
        self.currentView = currentView
        self.currentSuperview = currentSuperview
        super.touchesBegan(touches, with: event)
    }
    
    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) {
        var center = self.currentView.center
        let currentLocation = self.touch.location(in: self.currentSuperview)
        let previousLocation = self.touch.previousLocation(in: self.currentSuperview)
        let yTranslation = currentLocation.y - previousLocation.y
        center.y += yTranslation
        self.view!.center = center
        super.touchesMoved(touches, with: event)
    }
    
    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) {
        for subview in self.currentSuperview.subviews {
            // this goes through all the sibling views including the non-calendar-event views i.e. calendar dates, calendar frame, etc
            // so make sure to sort those out
            if subview != self.currentView! && self.currentView!.frame.intersects(subview.frame) {
                var center = self.currentView.center
                let isHigher = subview.center.y >= center.y
                // isHigher >= 0 means the current view that you've selected is located higher
                // than the overlapping view below
                if isHigher {
                    center = CGPoint(x: subview.center.x, y: subview.center.y - self.currentView.bounds.height)
                    self.view!.center = center
                } else {
                    center = CGPoint(x: subview.center.x, y: subview.center.y + self.currentView.bounds.height)
                    self.view!.center = center
                }
            }
        }
        super.touchesEnded(touches, with: event)
    }
}

根据您拖动的日历事件是在重叠视图的上侧还是下侧,它会移动到相邻的位置。随意为其添加变换动画。