1

I am building a app where you can drag images inside a view. Currently it look like this:

enter image description here

enter image description here

As you can see I marked the background color from the image view in green. The image view has contentMode aspectFit and it is 40 pixels smaller than the black view behind it. I want the that the image is the full length and width of the image view. The contentMode should be aspectFit, that nothing is cut away from the image. Is it possible to resize the image, that it has 20 pixels or a bit more space from the view?

adri567
  • 533
  • 5
  • 20
  • `.scaleToFill` you don't crop the image, but will be stretched. With `aspectFill` you don't display the entire image, but looks better – Toto Mar 02 '20 at 15:26
  • is there a way without stretching the image? – adri567 Mar 02 '20 at 15:32
  • you better show the image like that (.aspectFit) if there is where you preview your image, while when you display in small layout you should use .aspectFill for your thumbnail images even if you lose o bit of edge. – Toto Mar 02 '20 at 15:35
  • @adri567 - your question is a little confusing... Do you want a 20-pixel "green frame" around the image? With the green frame centered horizontally and vertically? – DonMag Mar 02 '20 at 16:04
  • Sorry, I'm not very good on english. I want something similar to this question: https://stackoverflow.com/questions/26833627/with-auto-layout-how-do-i-make-a-uiimageviews-size-dynamic-depending-on-the-im – adri567 Mar 02 '20 at 16:10
  • 1
    @adri567 - are you laying out your image view in Storyboard? Or via code? – DonMag Mar 02 '20 at 16:41
  • @DonMag via code – adri567 Mar 02 '20 at 16:59

4 Answers4

2

@adri567 You should use UIViewContentModeScaleToFill property like

imageView.contentMode = .scaleToFill

Try with this!

Ram
  • 764
  • 1
  • 7
  • 20
  • but after this the image is stretched – adri567 Mar 02 '20 at 15:30
  • Then you need to put `UIViewContentModeScaleAspectFill`. – Ram Mar 02 '20 at 15:33
  • I want the whole image. If I use AspectFill some parts of the image is cropped away. :/ – adri567 Mar 02 '20 at 15:35
  • Then the problem on your image ratio. Have you picked original image or edited image by image picker controller? cause the picked image ratio must be greater than your frame width and height you could see the entire image when using scaleToFill. Otherwise you can't. – Ram Mar 02 '20 at 15:38
  • I picked my image with original image. – adri567 Mar 02 '20 at 15:40
  • @adri567 you cannot fill your image without cropped or stretched image – Vicky_Vignesh Mar 02 '20 at 15:45
  • yeah, but when I use aspectFill, some parts of the image are cropped away – adri567 Mar 02 '20 at 15:46
  • 2
    @adri567 you cannot satisfy both condition stretched and cropped ! you cannot achieve filling the image with whole content unless you lose one and the property to fill the whole content without stretching is `UIViewContentModeScaleAspectFill` – Vicky_Vignesh Mar 02 '20 at 15:49
  • 2
    @adri567 Seems you tried to display landscape and portrait images. If you want full image means try with update your imageView frame based on you picked image width and height based on that image orientation. Then only you must see your desired output. – Ram Mar 02 '20 at 15:49
  • How can I achieve this to update the frame of the image view? – adri567 Mar 02 '20 at 15:57
  • 1
    You can get your picked image width and height and try to find Portrait or landscape based on width and height property of image as well as compared with your screen size. Then you can define content mode like AspectFit for Landscape Otherwise ScallToFill to portrait. – Ram Mar 02 '20 at 16:00
1

If you want to keep the image at the same size, but don't want to stretched it. your solution is something else.

  1. Display your image as .aspectFit as in the question

  2. the green view that you display replace it with the same image in .aspectFill but blur it as much as it looks good.

Toto
  • 593
  • 7
  • 20
  • 1
    But is there now way to give the image view a dynamic height? So it should be like 20pts away from the edges on the horizontal level. – adri567 Mar 02 '20 at 15:45
1

Simple math can solve this.

for shortcuts: H -> height , W -> Width

We know that general formula for this is: h1 / w1 = h2 / w2

Hscreen / Wscreen = Himage / Wimage

so we know screen width, image height and image width.

we can get screen width as -> view.frame.width

also we can get image size as -> image.size.width and image.size.height

Hscreen = (Himage) * (WScreen) / Wimage

..

you can use Hscreen to imageViews height anchor.

1

One approach...

  • embed a UIImageView in a (green) UIView
  • constrain the imageView on all 4 sides + 20-pts "padding"
  • constrain the width of the greenView (or its leading and trailing)
  • constrain the Y position of the greenView (top or centerY)
  • constrain the height of the imageView with a multiplier based on the image width and height

Here is a simple example:

class ViewController: UIViewController {

    let imgView: UIImageView = {
        let v = UIImageView()
        v.contentMode = .scaleToFill
        return v
    }()

    let greenView: UIView = {
        let v = UIView()
        v.backgroundColor = .green
        return v
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        // replace with your image name
        guard let img = UIImage(named: "bkg640x360") else {
            fatalError("Could not load image!")
        }

        view.backgroundColor = .black

        // set the imgView's image
        imgView.image = img

        // use auto-layout constraints
        imgView.translatesAutoresizingMaskIntoConstraints = false
        greenView.translatesAutoresizingMaskIntoConstraints = false

        // add imgView to greenview
        greenView.addSubview(imgView)

        // add greenView to self.view
        view.addSubview(greenView)

        // we want to respect safe-area
        let g = view.safeAreaLayoutGuide

        NSLayoutConstraint.activate([

            // constrain greenView leading and trailing to view (safeArea)
            greenView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
            greenView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),

            // constrain greenView centerY to view centerY
            greenView.centerYAnchor.constraint(equalTo: g.centerYAnchor, constant: 0.0),

            // constrain imgView to all 4 sides of greenView with 20-pts "padding"
            imgView.topAnchor.constraint(equalTo: greenView.topAnchor, constant: 20.0),
            imgView.bottomAnchor.constraint(equalTo: greenView.bottomAnchor, constant: -20.0),
            imgView.leadingAnchor.constraint(equalTo: greenView.leadingAnchor, constant: 20.0),
            imgView.trailingAnchor.constraint(equalTo: greenView.trailingAnchor, constant: -20.0),

            // constrain imgView proportional height equal to image height / width
            imgView.heightAnchor.constraint(equalTo: imgView.widthAnchor, multiplier: img.size.height / img.size.width),

        ])

    }

}

The result, using a 640 x 360 image:

enter image description here

and using a 512 x 512 (square) image:

enter image description here

These are my source images:

enter image description here

enter image description here

DonMag
  • 69,424
  • 5
  • 50
  • 86