如何将UI元素相对于背景图像放置在背景图像上

时间:2018-08-13 10:03:51

标签: ios swift

我以前在这里How to make full screen background image inside ScrollView and keep aspect ratio提问过,并从“ ekscrypto”获得了很好的询问,再次感谢您。

enter image description here

我在图像上有带有文本的按钮(1、2、3、4、5等),以前我使用硬编码的X和Y坐标将UI元素(按钮)放置在背景图像上,此解决方案适用于所有iPhone设备,而不是iPad。 我根据从“ ekscrypto”获得的解决方案更改了代码,现在当然该解决方案不适用于任何设备。

图像上有一条道路,我需要在这条道路上布置这些按钮。无论设备和图像比例如何,如何相对于图像正确定位此按钮?

P.S。 Ekscrypto还提供了UI元素定位的解决方案,但我不知道它是如何工作的。

这是我当前尝试创建按钮的方式:

let imageOne = UIImage(named: "level1") as UIImage?
let levelOne = UIButton(type: UIButtonType.system) 
levelOne.frame = CGRect.init(x: 10, y: 10, width: 100, height: 45)
levelOne.setImage(imageOne, for: .normal) 
scrollView.addSubview(levelOne)

但是iPhone和iPad的按钮位置和大小应该不同。如何相对于图像正确放置它们?

非常感谢ekscrypto,非常抱歉延迟答复。您的代码可以正常工作,并且可以解决我的问题,但是有一个小问题。

  1. 必须将此行更改为让button = UIButton(type:.system)更改为.custom,否则您将获得蓝色填充的按钮,而不是背景图像。

  2. 带有背景图片的按钮太大,尤其是在iPhone 5上,更改为让backgroundDesignHeight:CGFloat = 330.0改为730以使其更小

  3. iPhone和iPad上的所有按钮都在同一位置,除了“ plus设备”外,底部(向下)按钮的偏移量应稍高一些

  4. 在某些设备上,按钮上的背景图像有些模糊,这是在将backgroundDesignHeight更改为730之后发生的

2 个答案:

答案 0 :(得分:1)

您可以通过以下几种方法解决此问题:

  • 根据当前屏幕尺寸和“设计”尺寸手动计算最终的x / y位置
  • 手动创建基于长宽比的约束,让iOS为您计算最终位置

假设设备/应用的方向是恒定的(始终为横向或始终为纵向)并且始终为全屏,则手动计算可能会更容易。

首先,您将需要一个辅助函数来调整图像大小:

private func scaledImage(named imageName: String, scale: CGFloat) -> UIImage? {
    guard let image = UIImage(named: imageName) else { return nil }
    let targetSize = CGSize(width: image.size.width * scale, height: image.size.height * scale)
    return resizeImage(image: image, targetSize: targetSize)
}

// Adapted from https://stackoverflow.com/questions/31314412/how-to-resize-image-in-swift
private func resizeImage(image: UIImage, targetSize: CGSize) -> UIImage? {
    let size = image.size

    let widthRatio  = targetSize.width  / size.width
    let heightRatio = targetSize.height / size.height

    // Figure out what our orientation is, and use that to form the rectangle
    var newSize: CGSize
    if(widthRatio > heightRatio) {
        newSize = CGSize(width: size.width * heightRatio, height: size.height * heightRatio)
    } else {
        newSize = CGSize(width: size.width * widthRatio, height: size.height * widthRatio)
    }


    // This is the rect that we've calculated out and this is what is actually used below
    let rect = CGRect(x: 0, y: 0, width: newSize.width, height: newSize.height)

    // Actually do the resizing to the rect using the ImageContext stuff
    UIGraphicsBeginImageContextWithOptions(newSize, false, 1.0)
    image.draw(in: rect)
    let newImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return newImage
}

接下来,我们将创建一个函数来计算按钮的位置以及基于图像大小的按钮大小:

private func positionScaledButton(x designX: CGFloat, y designY: CGFloat, imageName: String) -> UIButton {

    // First, compute our "designScale"
    let screenHeight = UIScreen.main.bounds.size.height
    let backgroundDesignHeight: CGFloat = 330.0 // ** see below
    let designScale = screenHeight / backgroundDesignHeight


    // Create button
    let button = UIButton(type: .custom)

    // Get image to use, and scale it as required
    guard let image = scaledImage(named: imageName, scale: designScale) else { return button }

    button.frame = CGRect(x: designX * designScale, y: designY * designScale, width: image.size.width, height: image.size.height)
    button.setImage(image, for: .normal)
    scrollView.addSubview(button)
    return button
}

**上面代码中的值“ 330.0”是指滚动器中背景图像的高度,从中可以测量按钮的x / y坐标。

对于图片“ levelOne”,假设按钮的左上角应位于x:10,y:10:

let levelOneButton = positionScaledButton(x: 10, y: 10, imageName: "imageOne")
// To do: addTarget event handler

答案 1 :(得分:0)

使用相对点,而不是绝对点。

因此,与其说按钮1位于(30, 150)的点上,不如说是使用屏幕尺寸的分数,而是使用屏幕尺寸的(0.0369, 0.4)-然后使用这些分数来创建自动布局约束。