ios - 判断 UIView 数组中的 UIView 是否完全重叠,然后调整位置

标签 ios swift uiview cgpoint

我在下面有一个循环,它应该检测 UIView 数组中的 View 是否完全相互重叠。如果他们这样做,则调整他们的 center 值。

每个 View 都是 25x25。

func drawCircles() {
        for i in 0..<circles.count{
            circles[i].center = getRandomPoint()
            for j in 0..<circles.count{
                if(i != j) {
                    let comparingCentre = circles[j].center
                    let dist = distance(comparingCentre, circles[i].center)
                    if dist <= 25 {
                        
                        var newCenter = circles[i].center
                        var centersVector = CGVector(dx: newCenter.x - comparingCentre.x, dy: newCenter.y - comparingCentre.y)
                     
                        //Circle width is 25
                        centersVector.dx *= 26 / dist
                        centersVector.dy *= 26 / dist
                        newCenter.x = comparingCentre.x + centersVector.dx
                        newCenter.y = comparingCentre.y + centersVector.dy
                        circles[i].center = newCenter
                    }
                }
            }
        }
...
}

下面是生成随机 CGPoint 的方法,它被设置为 View 的中心:

func getRandomPoint() -> CGPoint {
    let viewMidX = self.circlesView.bounds.midX
    let viewMidY = self.circlesView.bounds.midY
    
    let xPosition = self.circlesView.frame.midX - viewMidX + CGFloat(arc4random_uniform(UInt32(viewMidX*2)))
    let yPosition = self.circlesView.frame.midY - viewMidY + CGFloat(arc4random_uniform(UInt32(viewMidY*2)))
    let point = CGPoint(x: xPosition, y: yPosition)
    return point
}

下面是确定两个 UIView 之间距离的方法。

func distance(_ a: CGPoint, _ b: CGPoint) -> CGFloat {
    let xDist = a.x - b.x
    let yDist = a.y - b.y
    return CGFloat(hypot(xDist, yDist))
}

但是,我仍然偶尔会遇到两个 View 相互重叠的情况(请参阅下面的红色圆圈部分):

enter image description here

编辑 这是将圆圈添加到 View 的代码:

func generateCircles() {
    numberOfCircles = Int.random(in: 1..<50)
    let circleWidth = CGFloat(25)
    let circleHeight = circleWidth
    
    var i = 0
    while i < numberOfCircles {
        let circleView = CircleView(frame: CGRect(x: 0.0, y: 0.0, width: circleWidth, height: circleHeight))
        let number = Int.random(in: 0..<2)
        if number == 1 {
            circleView.mainColor = .yellow
        } else {
            circleView.mainColor = .blue
        }
      
        circles.append(circleView)
        i += 1
    }
    drawCircles()
}

最佳答案

根据我上面关于将比较距离的逻辑移动到随机点的创建的评论,这里有一个快速选项: 这可以清理,但我不想完全重写它并尽可能多地使用您的代码。

generateCirles 函数中,我只更改了 CircleView 的初始化方式

func generateCircles() {
    numberOfCircles = Int.random(in: 1..<50)
    
    let circleWidth = CGFloat(25)
    let circleHeight = circleWidth
    
    for _ in 0..<numberOfCircles {
        let circleView = CircleView(frame: CGRect(origin: getRandomPoint(), size: (CGSize(width: circleWidth, height: circleHeight))))
        let number = Int.random(in: 0..<2)
        if number == 1 {
            circleView.mainColor = .yellow
        } else {
            circleView.mainColor = .blue
        }
        
        circles.append(circleView)
    }
    drawCircles()
}

getRandomPoint 中,我添加了一个检查,以根据您现有的距离逻辑查看新点是否是有效点:

func getRandomPoint() -> CGPoint {
    let viewMidX = self.circlesView.bounds.midX
    let viewMidY = self.circlesView.bounds.midY
    
    let xPosition = self.circlesView.frame.midX - viewMidX + CGFloat(arc4random_uniform(UInt32(viewMidX*2)))
    let yPosition = self.circlesView.frame.midY - viewMidY + CGFloat(arc4random_uniform(UInt32(viewMidY*2)))
    let point = CGPoint(x: xPosition, y: yPosition)
    
    if !validatePoint(point) {
        return getRandomPoint()
    }
    return point
}

func validatePoint(_ point: CGPoint) -> Bool {
    for circle in circles {
        if distance(circle.frame.origin, point) <= 25 {
            return false
        }
    }
    return true
}

而且我从您发布的 drawCircles 中删除了您的所有代码。

这是 300 个圆圈的样子:(我使用 View 框架作为 circlesView 框架,所以这就是圆圈与屏幕边界重叠的原因)这对你来说应该不是问题,因为我假设你circlesView 框架设置得更小。 enter image description here

关于ios - 判断 UIView 数组中的 UIView 是否完全重叠,然后调整位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64145331/

相关文章:

ios - iOS 中的 UIAlertView 委托(delegate)协议(protocol)

ios - 以编程方式向 UITableview 添加 header

来自 [String : AnyObject] 的 iOS Swift 值

ios - 如何在 Swift 中获取堆栈跟踪错误?

objective-c - 我们可以做些什么来让我们自定义 UIView 的用户可以在 XIB 中自定义那个 UIView?

ios - 红色组名颜色

ios - SFAuthenticationSession/ASWebAuthenticationSession 和注销

objective-c - var Array 类型的 Swift 类字段被转换为不可变的 NSArray 而不是 NSMutableArray

ios - 获取由 UIView 的 animateWithDuration 创建的动画的引用或通过任何其他方式识别它

ios - Swift,如何将现有的 uiview 转换为 uiscrollview?