【问题标题】:How do I place the objects in the array around the center image?如何将对象放置在中心图像周围的阵列中?
【发布时间】:2016-03-18 17:09:36
【问题描述】:

我有一组按钮,当我将它们附加到视图时,我希望将它们定位在中心的图像视图周围。根据数组中有多少对象,我希望它们围绕整个圆圈均匀分布。以下是我的尝试。我做错了什么,我应该如何解决?驼鹿背后有不止一个按钮。

var userbutton = [UIButton]()
var upimage = [UIImage]()
var locationpic = [AnyObject]()

 func locationsSet(){

    for (index, users) in upimage.enumerate() {

        let userbutton = UIButton()
        userbutton.addTarget(self, action: "buttonAction:", forControlEvents: .TouchUpInside)
        userbutton.frame = CGRectMake(100, 100, 50, 50)
        userbutton.layer.cornerRadius = userbutton.frame.size.width/2
        userbutton.clipsToBounds = true
        userbutton.setImage(users, forState: .Normal)

        let radians = CGFloat(M_PI) * 2.0 / CGFloat(upimage.count) * CGFloat(index)

        let centerx = self.view.bounds.width / 2.0
        let radius =  currentuserpic.frame.size.width / 2.0
        let centery = self.view.bounds.height / 2.0

        let pointx = centerx + cos(radians) * (radius + 40)
        let pointy = (centery) + (sin(radians)) * (radius + 40)

        userbutton.center.x = pointx
        userbutton.center.y = pointy

        self.userbutton.append(userbutton)
        self.view.addSubview(userbutton)

        print("x\(pointx)")
        print("y\(pointy)")


    }


}

【问题讨论】:

  • 这不是教程。
  • 这不是家庭作业。这是我自己的个人应用程序。
  • 我被卡住了我不是要你写代码,我只是想弄清楚如何根据有多少对象将数组中的按钮定位在某个位置数组。

标签: ios swift layout


【解决方案1】:

我会怎么做:

创建 UIView 的扩展以获取对角线和半径。这些很方便,因为我们希望我们的“卫星”即使在“行星”不是正方形的情况下也有可预测的位置。

extension UIView {

    var diagonal : CGFloat {
        return sqrt(pow(self.frame.width, 2) + pow(self.frame.height, 2))
    }

    var radius : CGFloat {
        return diagonal / 2
    }
}

这将根据与原点的角度和距离返回一个点。 它使用了可怕的三角函数。

func getPoint(fromPoint point: CGPoint, atDistance distance: CGFloat, withAngleRadians angle:CGFloat) -> CGPoint {

    let x = point.x
    let y = point.y

    let dx = (distance * cos(angle))
    let dy = (distance * sin(angle))

    return CGPoint(x: (dx + x), y: (dy + y))
}

现在是真正的功能。以圆形图案生成一堆点。我对角度使用了运行总和,而不是每次都乘以索引。这只是返回视图的中心点。

func encirclePoint(point : CGPoint, distance:CGFloat, inParts parts: Int) -> [CGPoint] {

    let angle = 2 * CGFloat(M_PI) / CGFloat(parts) // critical part, you need radians for trigonometry
    var runningAngle : CGFloat = -(CGFloat(M_PI) / 2) // start at the top

    var points : [CGPoint] = []

    for _ in 0..<parts {
        let circlePoint = getPoint(fromPoint: point, atDistance: distance, withAngleRadians: runningAngle)
        points.append(circlePoint)
        runningAngle += angle
    }

    return points
}

现在您可以创建一个简单的函数,该函数接受一个视图、一个边距和一组“卫星”视图。它将设置它们的中心并将它们添加到我们用于输入的视图的超级视图中。不将它们添加到视图本身是有意义的,因为它们可能不会放置在其中。

func encircleView(view : UIView, withSubViews subViews : [UIView], withMargin margin : CGFloat) {

    guard !(subViews.isEmpty) else { // if there are no subviews : abort
        return
    }

    let distance = view.radius + margin
    let points = encirclePoint(view.center, distance: distance, inParts: subViews.count)

    guard subViews.count == points.count, let uberView = view.superview else { // if the count is not the same or there is no superview: abort
        return
    }

    for (point, subView) in zip(points, subViews) { subView.center = point }
}

请注意,除了这些函数中的中心计算之外,我什么也没做。为它们设计样式进入另一个功能。这使得维护和调试变得超级容易。

我什至可以让最后一个函数只返回带有更新帧的子视图,然后再添加它们。



或负边距:)

Gist

【讨论】:

    【解决方案2】:

    一个完整的圆是 2 * pi 弧度。您需要将其除以您拥有的项目数,然后将其乘以您当前正在处理的项目的索引。使用三角函数查找圆圈上的位置:

    for (index, users) in upimage.enumerate() {
        let radians = CGFloat(M_PI) * 2.0 / CGFloat(upimage.count) * CGFloat(index)
    
        ......
    
        let centerx = self.view.bounds.width / 2.0
        let radius =  currentuserpic.frame.size.width / 2.0
        let centery = self.view.bounds.height / 2.0
    
        let pointx = centerx + cos(radians) * radius
        let pointy = centery + sin(radians) * radius
    
        ......
    }
    

    【讨论】:

    • 我输入了一些CGFloats,包括@RMenke(谢谢!)在计算radians时建议的那个。看看吧。
    • 看起来当您从 2 个用户移动到 3 个用户时,您只是添加了更多子视图,而没有清除之前的子视图。您可以保留一组活动子视图,并在需要删除它们时调用removeFromSuperview
    • 在添加新的用户按钮之前,用for button in userButton { button.removeFromSuperview() }; userButton = []清除旧按钮
    • 我在您发布的 png 中没有看到任何错误。该代码应该是您在 func locationsSet() { 中执行的第一件事。
    • 谢谢,但由于某种原因,按钮的间距不均匀 puu.sh/lTA5Y/da2ce9d364.png。
    猜你喜欢
    • 1970-01-01
    • 2015-10-08
    • 2021-04-26
    • 1970-01-01
    • 2014-10-15
    • 2021-08-08
    • 2015-07-02
    • 2023-01-27
    • 1970-01-01
    相关资源
    最近更新 更多