Я пытаюсь получить вид на верхнюю часть изображения.У меня есть приложение xCode с изображением iPhone в UIImageView и UIView, которое позиционирует себя поверх изображения для отображения экранов iPhone.Это работало в более ранних выпусках, потому что изображение было статического размера, но теперь мне нужно масштабировать изображение, чтобы заполнить экран для новых устройств, таких как iPhone X. Думаю, Aspect Fit является частью ответа.Мне нужно, чтобы рассматриваемый вид располагался правильно на всех устройствах iPhone и симуляторах.У меня есть некоторый код, который, кажется, работает для устройств, но тогда этот же код работает по-другому в симуляторах.Мне нужно, чтобы код работал в симуляторах и устройствах одинаково, поскольку у меня нет всех устройств для тестирования.
Как я могу, используя раскадровку или код, расположить прямоугольник поверх изображениячто масштабируется системой?Нужно универсальное решение, которое работает на всех устройствах и в симуляторе.
Я включаю грубые примеры кода, с которыми я экспериментировал.
- Файл WeedplatesViewController.swift содержит код для устройств, который, кажется, правильно позиционируется для устройств, а затем аналогичный код, который я скопировал и настраивал для тестирования симуляторов, которые неправильно позиционируются.Имейте расширение UIImage, чтобы создать изображение представления и затем некоторый код, чтобы искать черный прямоугольник в изображении.Использование кода сравнения пикселей, найденного здесь, при переполнении стека.
На раскадровке находится контроллер представления Weedpaper с заголовком Weedpaper, текстом «для Apple iPhone», изображением iPhone, UIView, который я хочучтобы правильно расположить верхнюю часть изображения iPhone, текст «количество установленных Weedpapers» и ряд кнопок автоматического изменения размера в нижней части.
- Сначала получил сложный урок, используя ограничения раскадровки для позиционирования прямоугольника.и, кажется, может заставить его работать в раскадровке, но не работает на устройствах или симуляторах.
- Попробовал жестко запрограммировать позицию, которая, казалось, работала на устройствах, но не работала на симуляторе, и наоборот, и занимаетдлинный тест и явно не правильный способ сделать это.
- Затем изменил файл png, поместив черный (255,255,255) прямоугольник в файл изображения iPhone, затем в коде скопировал это представление в UIImageи попытался найти пиксели черного прямоугольника, которые представляют кадр.Как только пиксели будут найдены, вы сможете позиционировать вид, используя эти координаты.Но я получаю разные растровые изображения скриншотов от устройств против симуляторов.
- Также пробовал использовать AVMakeRect (aspectRatio: CGSize (width: w, height: h), insideRect: self.uiImageView.bounds) безрезультатно.
Требуется UIView для размещения в верхней части изображения, которое масштабируется системой на устройствах и симуляторе.
override func viewDidAppear(_ animated: Bool) {
if (UIDevice.modelName.contains("Simulator"))
{
deviceName = ProcessInfo.init().environment["SIMULATOR_DEVICE_NAME"] ?? "NoN"
bSimulator = true
}
else
{
deviceName = UIDevice.modelName
bSimulator = false
}
print("deviceName:", deviceName)
print("simulator:", bSimulator)
var frame:CGRect!
if bSimulator{
frame = self.getImageRectForSimulators()
}
else
{
frame = self.getImageRectForDevices()
}
self.uiViewPhotos.frame = frame
self.uiViewPhotos.isHidden = false
}
func getImageRectForDevices() -> CGRect
{
// Write the view to an image so we can get the positioning rectangle
// Positioning Rectangle is a black rectangle in the image
// it has the only true black pixels in the image
let imgView:UIImageView = self.uiImageView
let img:UIImage = self.uiImageView.asImage()
// Write to the photo album for testing
//UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil)
var pixelData = img.cgImage!.dataProvider!.data
var data: UnsafePointer<UInt8> = CFDataGetBytePtr(pixelData)
let maxX = img.size.width
let maxY = img.size.height
let halfwayX = maxX / 2
let halfwayY = maxY / 2
let screenScale = UIScreen.main.scale
let scaleFactorX = img.scale
let scaleFactorY = img.scale * screenScale
let screenFactor = UIScreen.main.bounds.width/UIScreen.main.bounds.height
let imgViewFactor = self.uiImageView.frame.width/self.uiImageView.frame.height
var pnt:CGPoint = CGPoint(x: -1, y: -1)
var pixelInfo: Int = -1
var r:CGFloat!, g:CGFloat!
var b:CGFloat!, a:CGFloat!
var uiColor:UIColor!
var v1:CGFloat!, v2:CGFloat!
var v3:CGFloat!, v4:CGFloat!
var newRect:CGRect!
// Find this color in the image to locate the black pixel frame
// use that to size the view accordingly
// Seems to change among devices so round use black color
let uiColor_phoneFramePixelColor = UIColor(red:0.0, green:0.0, blue:0.0, alpha:1.0)
// Device code
for i in stride(from: halfwayX*scaleFactorX, to: 0, by: -1)
{
pnt.x = i
pnt.y = halfwayY*scaleFactorY
pixelInfo = ((Int(img.size.width) * Int(pnt.y)) + Int(pnt.x)) * 4
r = CGFloat(data[pixelInfo])/CGFloat(255.0)
g = CGFloat(data[pixelInfo+1])/CGFloat(255.0)
b = CGFloat(data[pixelInfo+2])/CGFloat(255.0)
a = CGFloat(data[pixelInfo+3])/CGFloat(255.0)
uiColor = UIColor(red: r, green: g, blue: b, alpha: a)
print("searching for i black pixel at i, y:", i, pnt.y, 255.0*r, 255.0*g, 255.0*b, a)
if (uiColor == uiColor_phoneFramePixelColor)
{
v1 = i
print("found i pixel at:", i)
break
}
}
print(" ")
// find top y pixel
// Device code
for j in stride(from: halfwayY*scaleFactorY, to: 0, by: -1)
{
pnt.x = halfwayX*scaleFactorX
pnt.y = j
pixelInfo = ((Int(img.size.width) * Int(pnt.y)) + Int(pnt.x)) * 4
r = CGFloat(data[pixelInfo])/CGFloat(255.0)
g = CGFloat(data[pixelInfo+1])/CGFloat(255.0)
b = CGFloat(data[pixelInfo+2])/CGFloat(255.0)
a = CGFloat(data[pixelInfo+3])/CGFloat(255.0)
uiColor = UIColor(red: r, green: g, blue: b, alpha: a)
print("searching for j black pixel at j, x:", j, pnt.x, 255.0*r, 255.0*g, 255.0*b, a)
if (uiColor == uiColor_phoneFramePixelColor)
{
v2 = j
print("found j pixel at:", j)
break
}
}
print(" ")
// Find bottom x pixel
// Device code
for k in stride(from: halfwayX*scaleFactorX, to: maxX*scaleFactorX, by: 1)
{
pnt.x = k
pnt.y = halfwayY
pixelInfo = ((Int(img.size.width) * Int(pnt.y)) + Int(pnt.x)) * 4
r = CGFloat(data[pixelInfo])/CGFloat(255.0)
g = CGFloat(data[pixelInfo+1])/CGFloat(255.0)
b = CGFloat(data[pixelInfo+2])/CGFloat(255.0)
a = CGFloat(data[pixelInfo+3])/CGFloat(255.0)
uiColor = UIColor(red: r, green: g, blue: b, alpha: a)
print("searching for k black pixel at k, y:", k, pnt.y, 255.0*r, 255.0*g, 255.0*b, a)
if (uiColor == uiColor_phoneFramePixelColor)
{
v3 = k
print("found bottom k pixel at:", k)
break
}
}
print(" ")
// Find bottom y pixel
// Device code
for l in stride(from: halfwayY*scaleFactorY, to: maxY*scaleFactorY, by: 1)
{
pnt.x = halfwayX
pnt.y = l
pixelInfo = ((Int(img.size.width) * Int(pnt.y)) + Int(pnt.x)) * 4
r = CGFloat(data[pixelInfo])/CGFloat(255.0)
g = CGFloat(data[pixelInfo+1])/CGFloat(255.0)
b = CGFloat(data[pixelInfo+2])/CGFloat(255.0)
a = CGFloat(data[pixelInfo+3])/CGFloat(255.0)
uiColor = UIColor(red: r, green: g, blue: b, alpha: a)
print("searching for l black pixel at l, x:", l, pnt.x, 255.0*r, 255.0*g, 255.0*b, a)
if (uiColor == uiColor_phoneFramePixelColor)
{
v4 = l
print("found bottom l pixel at:", l)
break
}
}
print(" ")
// this is the Black Rectangle from the bitmap of the orginal image
let w = (v3 - v1)
let h = (v4 - v2)
newRect = CGRect(x: v1/scaleFactorX, y: v2/scaleFactorY, width: w/scaleFactorX, height: h/scaleFactorY)
print("calculated rectangle:", newRect)
return newRect
}
extension UIView {
func asImage()-> UIImage
{
// Get an image of the view. Apple discourages using UIGraphicsBeginImageContext
// Starting with IOS 10 UIGraphicsBeginImageContext is sRBG only and 32 bit only.
// Use UIGraphicsImageRenderer
if #available(iOS 10.0, *) {
let renderer = UIGraphicsImageRenderer(bounds: bounds)
let renderFormat = UIGraphicsImageRendererFormat.default()
renderFormat.opaque = false
let renderedImage = renderer.image {
rendererContext in
layer.render(in: rendererContext.cgContext)
}
return renderedImage
}
else{
UIGraphicsBeginImageContext(self.frame.size)
self.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return UIImage(cgImage: image!.cgImage!)
}
}
}