Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/36.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 如何从UIImageView获取显示的图像帧?_Iphone_Uiimageview - Fatal编程技术网

Iphone 如何从UIImageView获取显示的图像帧?

Iphone 如何从UIImageView获取显示的图像帧?,iphone,uiimageview,Iphone,Uiimageview,我修改UIImageView的contentMode属性。因此,我的图像的帧不等于UIImageView的帧。我的问题是如何从UIImageView检索图像的帧 let frameIdentifyBorderView = UIView(frame: imageFrameInImageView) frameIdentifyBorderView.layer.borderWidth = 3 frameIdentifyBorderView.layer.borderColor =

我修改UIImageView的contentMode属性。因此,我的图像的帧不等于UIImageView的帧。我的问题是如何从UIImageView检索图像的帧

    let frameIdentifyBorderView = UIView(frame: imageFrameInImageView)
    frameIdentifyBorderView.layer.borderWidth = 3
    frameIdentifyBorderView.layer.borderColor = UIColor.blueColor().CGColor

    imageView.addSubview(frameIdentifyBorderView)
如以下示例所示,橙色矩形是UIImageView的边框。很明显,图像的帧与UIImageView不同

    let frameIdentifyBorderView = UIView(frame: imageFrameInImageView)
    frameIdentifyBorderView.layer.borderWidth = 3
    frameIdentifyBorderView.layer.borderColor = UIColor.blueColor().CGColor

    imageView.addSubview(frameIdentifyBorderView)

如果它是
UIViewContentModeScaleAspectFit
,它是这样的:

UIImageView *iv; // your image view
CGSize imageSize = iv.image.size;
CGFloat imageScale = fminf(CGRectGetWidth(iv.bounds)/imageSize.width, CGRectGetHeight(iv.bounds)/imageSize.height);
CGSize scaledImageSize = CGSizeMake(imageSize.width*imageScale, imageSize.height*imageScale);
CGRect imageFrame = CGRectMake(roundf(0.5f*(CGRectGetWidth(iv.bounds)-scaledImageSize.width)), roundf(0.5f*(CGRectGetHeight(iv.bounds)-scaledImageSize.height)), roundf(scaledImageSize.width), roundf(scaledImageSize.height));

事实上,它是iOS 4内置的(对于
UIViewContentModeScaleAspectFit
):

由于帧组件可能不是整数,请考虑用< /P>包装调用。

CGRectIntegral(…)
有关更多技巧,请参阅

 if you want to calculate it yourself, use below code written by me.

func getImageFrameInImageView(imageView : UIImageView) -> CGRect {
    /*
    by 徐明刚, ericxu1983@163.com
    算法:
        设高宽比 r = h/w, 则:r(imageView) 缩写成r(v), r(image)缩写为r(i), 
        if r(i) > r(v), 则
        h(i) = h(v), 
        h(i) / w(i) = r(i) -> w(i) = h(i) / r(i)
        y = 0
        x = (w(v) / 2)  - (w(i) / 2)
    反之
    */

    let image = imageView.image!
    let wi = image.size.width
    let hi = image.size.height
    print("wi:\(wi), hi:\(hi)")

    let wv = imageView.frame.width
    let hv = imageView.frame.height
    print("wv:\(wv), hv:\(hv)")

    let ri = hi / wi
    let rv = hv / wv
    print("ri:\(ri), rv:\(rv)")

    var x, y, w, h: CGFloat

    if ri > rv {
        h = hv
        w = h / ri
        x = (wv / 2) - (w / 2)
        y = 0
    } else {
        w = wv
        h = w * ri
        x = 0
        y = (hv / 2) - (h / 2)
    }

    return CGRect(x: x, y: y, width: w, height: h)
}
为了测试函数是否正确,我在UIImageView中使用了另一个视图来标识图像的边界

    let frameIdentifyBorderView = UIView(frame: imageFrameInImageView)
    frameIdentifyBorderView.layer.borderWidth = 3
    frameIdentifyBorderView.layer.borderColor = UIColor.blueColor().CGColor

    imageView.addSubview(frameIdentifyBorderView)


太好了

使用来自AVFoundation的此api

#import <AVFoundation/AVFoundation.h>

CGRect imageRect = 
    AVMakeRectWithAspectRatioInsideRect(imageView.image.size, imageView.bounds);
#导入
CGRect imageRect=
AVMakeRectWithAspectRatioInsideRect(imageView.image.size,imageView.bounds);
最简单的方法是使用。只需导入AVFoundation,就可以在一行代码中获得rect。斯威夫特4。请确保导入AVFoundation

import UIKit
import AVFoundation

class ViewController: UIViewController {

    var imageView = UIImageView()
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        imageView.frame = self.view.bounds
        imageView.contentMode = .scaleAspectFit
        imageView.backgroundColor = .blue
        imageView.autoresizingMask = [.flexibleWidth,.flexibleHeight]
        self.view.addSubview(imageView)
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

        URLSession.shared.dataTask(with: URL(string: "https://images.pexels.com/photos/248797/pexels-photo-248797.jpeg?w=940&h=650&dpr=2&auto=compress&cs=tinysrgb")!) { (data, response, error) in
            guard let dt = data else{print("error");return}
            DispatchQueue.main.async {
                guard let image = UIImage(data: dt) else{print("error");return}
                self.imageView.image = image
                self.imageView.layoutIfNeeded()
                let realImageRect = AVMakeRect(aspectRatio: image.size, insideRect: self.imageView.bounds)


                //proof
                let view = UIView(frame: realImageRect)
                view.layer.borderColor = UIColor.green.cgColor
                view.layer.borderWidth = 3
                self.view.addSubview(view)
            }
        }.resume()
    }
}

现在很容易

import AVKit
    
let rect = AVMakeRect(aspectRatio: image.size, insideRect: containerView.bounds);

因此,UIImageView没有直接的方法来检索图像帧。它需要手工计算,对吗?是的。事实上,它甚至似乎没有一个私有方法根据
contentMode
返回图像帧。我猜计算是在
-drawRect:
-sizeThatFits:
中执行的。我尝试了sizeThatFits:,它无法检索图像的帧。我更改了UIImageView的实现。如果我必须自己计算imageFrame,我会选择contentMode UIViewContentModeScaleToFill。这是可行的,但您应该从
cRectmake
中删除
floorf
函数。它们不是必需的(CGrect接受CGFloats),最好让iOS来处理舍入。在移除
floorf
之前,我的尺寸偶尔会减少一个像素。在将
floorf
添加到相框尺寸之前,我的尺寸偶尔会减少一个像素。所以最后一行应该是(至少对我来说):
CGRect-imageFrame=CGRectMake(floorf(0.5f*(CGRectGetWidth(iv.bounds)-scaledImageSize.width)),floorf(0.5f*(CGRectGetHeight(iv.bounds)-scaledImageSize.height)),floorf(scaledImageSize.width))
我认为应该是
让realmagerect=AVMakeRect(aspectRatio:image.size,inside:self.imageView.frame)
bounds
返回相对于superview没有x和y的大小。非常感谢。作为UIImageView扩展中的imageFrame属性,它甚至更好。