首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在这些UIImageViews之间保持图像的位置和大小不变?

如何在这些UIImageViews之间保持图像的位置和大小不变?
EN

Stack Overflow用户
提问于 2020-01-12 16:40:17
回答 2查看 72关注 0票数 0

如你所见,我有一个霓虹灯卡带的场景。在界面构建器中,我创建了3个UIImageViews,一个用于盒式磁带的背景,2个用于左右轴。这个想法是,这些纺锤体根据状态向后或向前旋转(倒带、ffw或play)。如果我只在iPhone 8上运行它,我就可以这样做。但是,当我决定要在iPhone 11 Pro上运行它时,会发生以下情况:

无论我试图捏造什么奇怪的约束组合,我都无法让主轴在设备上遵循它们正确的位置/大小。我将不得不花一些时间寻找和阅读关于野兽是自动布局的指南,但直到那座山被攀登,我会感谢任何帮助!

编辑:

以下是我到目前为止所拥有的一个方案性的、描述性更强的版本:

代码语言:javascript
复制
override func viewDidLoad() {
    super.viewDidLoad()

    // Code to position/size cassette
    let cassette = UIImageView(image: UIImage(named: "cassette"))
    cassette.translatesAutoresizingMaskIntoConstraints = false
    cassette.contentMode = .scaleAspectFit
    view.addSubview(cassette)

    view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: cassette.bottomAnchor, constant: 44).isActive = true
    view.safeAreaLayoutGuide.trailingAnchor.constraint(equalTo: cassette.trailingAnchor, constant: 20).isActive = true
    cassette.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20).isActive = true
    cassette.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 44).isActive = true

    // Code to position/size spindles
    let spindleLeft = UIImageView(image: UIImage(named: "spindle"))
    spindleLeft.translatesAutoresizingMaskIntoConstraints = false
    spindleLeft.widthAnchor.constraint(equalToConstant: 74).isActive = true
    spindleLeft.heightAnchor.constraint(equalToConstant: 74).isActive = true
    cassette.addSubview(spindleLeft)

    spindleLeft.centerXAnchor.constraint(equalTo: cassette.centerXAnchor, constant: -130.0).isActive = true
    spindleLeft.centerYAnchor.constraint(equalTo: cassette.centerYAnchor, constant: -14.0).isActive = true

}

以下是这两项资产:

目前,我正试图找出是否有一些方法可以使用设备的aspectRatio,以及我应该使用什么UIImageView内容模式(方面匹配,方面填充)。也许我挖得太深了,有一种更简单的方法来处理这件事,而我没有看到.

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-01-13 02:01:27

仅仅靠自动收费表是不会这样做的。如果它是原始图像的一部分,你必须测量主轴在哪里,然后根据图像视图的实际大小以及它通过其内容模式放置图像的位置,从数学上将主轴放在那里。

让我们对一个主轴(左主轴)这样做。你上传的磁带图像是4824x2230。我们通过仔细的检查发现,如果卡带图像显示在全尺寸,主轴的中心应该在大约(1294,1000),它应该是500像素左右的一面。

这等于说,我们希望主轴的图像占据一个方框(相对于原来的盒式图像) (1045,750,500,500)。

好吧,但这只是图像。我们必须将主轴相对于描绘它的图像视图进行定位。

现在,我将在一个图像视图中显示盒式磁带,该图像视图由自动输出大小调整到一些较小的大小。(我可以在viewDidLayoutSubviews中发现它的大小,它是在autolayout完成工作之后运行的。)并让这个图像视图有一个适合方面的内容模式。图像将被调整大小,并且它的位置可能不会在图像视图的原点。

因此,您必须解决的问题(在代码中)是:在图像被调整大小和重新定位之后,关于图像视图的主轴框架在哪里?然后,您只需将纺锤图像视图放在那里。

这是来自viewDidLayoutSubviews的代码;cassette是盒式图像视图,spindle是纺锤体图像视图:

代码语言:javascript
复制
    let cassettebounds = cassette.bounds
    let cw = cassettebounds.width
    let ch = cassettebounds.height
    let w = 4824 as CGFloat
    let h = 2230 as CGFloat
    var scale = cw/w
    var imw = cw
    var imh = h*scale
    var imx = 0 as CGFloat
    var imy = (ch-imh)/2
    if imh > ch { // we got it backwards
        scale = ch/h
        imh = ch
        imw = w*scale
        imy = 0 as CGFloat
        imx = (cw-imw)/2
    }
    cassette.addSubview(spindle)
    spindle.frame.size.width = 500*scale
    spindle.frame.size.height = 500*scale
    spindle.frame.origin.x = imx + (1045*scale)
    spindle.frame.origin.y = imy + (750*scale)

以下是6s和11 Pro的结果:

如果我自己这么说的话,看上去真不错。对读者来说,右边的主轴是一个练习。

票数 1
EN

Stack Overflow用户

发布于 2020-01-13 10:47:48

谢谢你@马特的精彩回答。当我需要的是一种更基本的方法时,我肯定把太多的动力归功于汽车布局。我已经标记了他的答案正确,并将提供我的新代码,工作和支持各种大小的屏幕:

代码语言:javascript
复制
override func viewDidLoad() {
    super.viewDidLoad()

    // Code to position/size cassette
    cassette = UIImageView(image: UIImage(named: "cassette"))
    cassette.translatesAutoresizingMaskIntoConstraints = false
    cassette.isUserInteractionEnabled = true
    cassette.contentMode = .scaleAspectFit
    view.addSubview(cassette)

    view.safeAreaLayoutGuide.bottomAnchor.constraint(equalTo: cassette.bottomAnchor, constant: 44).isActive = true
    view.safeAreaLayoutGuide.trailingAnchor.constraint(equalTo: cassette.trailingAnchor, constant: 20).isActive = true
    cassette.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20).isActive = true
    cassette.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 44).isActive = true
}

override func viewDidLayoutSubviews() {
    spindleLeft = addSpindle(to: cassette, posX: 505, posY: 350)
    spindleRight = addSpindle(to: cassette, posX: 1610, posY: 350)
}

func addSpindle(to cassette: UIImageView, posX: CGFloat, posY: CGFloat) -> UIImageView {
    let cassetteBounds = cassette.bounds
    let cassetteWidth = cassetteBounds.width
    let cassetteHeight = cassetteBounds.height

    let cassetteImageWidth =  cassette.image!.size.width
    let cassetteImageHeight = cassette.image!.size.height

    var scale = cassetteWidth / cassetteImageWidth

    var spindleWidth = cassetteWidth
    var spindleHeight = cassetteImageHeight*scale
    var spindleX = 0 as CGFloat
    var spindleY = (cassetteHeight - spindleHeight)/2

    if spindleHeight > cassetteHeight {
        scale = cassetteHeight / cassetteImageHeight
        spindleHeight = cassetteHeight
        spindleWidth = cassetteImageWidth*scale
        spindleY = 0 as CGFloat
        spindleX = (cassetteWidth - spindleWidth)/2
    }

    let spindle = UIImageView(image: UIImage(named: "spindle"))
    cassette.addSubview(spindle)

    spindle.frame.origin.x = spindleX + (posX*scale)
    spindle.frame.origin.y = spindleY + (posY*scale)
    spindle.frame.size.width = spindle.image!.size.width*scale //299.0
    spindle.frame.size.height = spindle.image!.size.height*scale //299.0

    return spindle
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59705943

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档