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

Posted

技术标签:

【中文标题】当我通过点击创建 UIView 时,如何不让它们重叠?【英文标题】:How do I not let UIViews overlap when I create them by tapping? 【发布时间】:2020-12-07 10:42:19 【问题描述】:

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

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

【问题讨论】:

"每个事件都是一个 UIView" 我们看不到。 【参考方案1】:

强烈建议您发布自己的代码,以便我们了解您的总体方向。否则,这可能会浪费我们双方的努力。

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

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)
    

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

【讨论】:

哇,非常感谢!对不起,我不是很具体,但你一针见血,完美解决了我的问题。谢谢!

以上是关于当我通过点击创建 UIView 时,如何不让它们重叠?的主要内容,如果未能解决你的问题,请参考以下文章

如何创建自定义 UIView?

如何在快速按下按钮时添加独立的 UIView?

UIView 中的按钮在点击时没有效果

使用 XIB 创建自定义 UIView

如何在 iOS 中使用 UIView 动画显示 UIView,如 UIAction 表?

如何在 UIScrollView 上转到 UIView 的顶部