質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

90.35%

  • Swift

    9413questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

swift4 UIViewの縦の比率に画像の縦を合わせたい。

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,286

RyomaD

score 14

swift初学者です。
以下のような画像を
イメージ説明
以下のようなUIImage内で,
イメージ説明
以下のような形で表示させたいのですが、(UIViewの縦の比率に画像の縦を合わせる)やり方が解らずに困っています。どなたかご存知の方がいらっしゃればご教授いただけないでしょうか。
コードでもstorybord上からでも構いません。
イメージ説明
ちなみに Content Mode を Aspect Fillに設定した場合は、
以下のように出力されます。
イメージ説明

コードは以下になります。

@IBOutlet weak var mainStackView: UIStackView!
    @IBOutlet weak var navigationLabel: UILabel!
    @IBOutlet weak var finishEditingButton: UIButton! //編集の終了
    @IBOutlet weak var editPhotoView: UIView! //トリミングで残す範囲を可視化するためのUIView
    @IBOutlet weak var headerView: UIView!
    @IBAction func cancelButton(_ sender: Any) {
        dismiss(animated: true, completion: nil)
    }

    var image : UIImage!
    var imageView : UIImageView! //トリミング対象画像を表示するためのUIImageView
    var previousImages = [UIImage]()
    var nextImages = [UIImage]()
    var scaleZoomedInOut : CGFloat = 1.0 //拡大・縮小した時にはUIImageViewのサイズのみが変わるので、実際のUIImageのサイズとUIImageViewとの倍率の差を記録する
    var previousScaleZoomedInOut = [CGFloat]()
    var nextScaleZoomedInOut = [CGFloat]()


    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewWillAppear(true)
        finishEditingButton.addTarget(self, action: #selector(finishEdittingAlert), for: .touchUpInside)

        editPhotoView.layer.borderColor = UIColor.black.cgColor
        editPhotoView.layer.borderWidth = 1
        setUpPinchInOutAndDoubleTap()

        //load image and show UIImageView
        let appDelegate = UIApplication.shared.delegate as! AppDelegate
        image = appDelegate.photoLibraryImage
        previousScaleZoomedInOut.append(scaleZoomedInOut)
        createImageView(sourceImage: image, on: editPhotoView)
        mainStackView.bringSubview(toFront: headerView)
    }

    //ピンチイン/アウト・ダブルタップの検出
    func setUpPinchInOutAndDoubleTap(){
        // ピンチイン・アウトの準備
        let pinchGetsture = UIPinchGestureRecognizer(target: self, action: #selector(pinchAction(gesture:)))
        pinchGetsture.delegate = self as? UIGestureRecognizerDelegate

        self.editPhotoView.isUserInteractionEnabled = true
        self.editPhotoView.isMultipleTouchEnabled = true

        self.editPhotoView.addGestureRecognizer(pinchGetsture)
        // ダブルタップの準備
        let doubleTapGesture = UITapGestureRecognizer(target: self, action:#selector(doubleTapAction(gesture:)))
        doubleTapGesture.numberOfTapsRequired = 2
        self.editPhotoView.addGestureRecognizer(doubleTapGesture)
    }

    //画像の全体が把握できるように、画像本体(UIImage)の幅がスクリーンの幅よりも大きい時は、画像を画面の幅に合わせたUIImageViewとして表示するという処理を施す関数
    func createImageView(sourceImage: UIImage, on parentView: UIView){
        imageView = UIImageView(image: sourceImage)
        // 画像の幅・高さの取得
        let imageWidth = sourceImage.size.width
        let imageHeight = sourceImage.size.height
        let screenWidth = editPhotoView.frame.width
        let screenHeight = editPhotoView.frame.height

        if scaleZoomedInOut == 1.0{
            if imageWidth > screenWidth{
                scaleZoomedInOut = screenWidth/imageWidth
            }
        }

        let rect:CGRect = CGRect(x:0, y:0, width:scaleZoomedInOut*imageWidth, height:scaleZoomedInOut*imageHeight)
        imageView.frame = rect// ImageView frame をCGRectで作った矩形に合わせる
        imageView.contentMode = .scaleAspectFill // Aspect Fill = 縦横の比率はそのままで短い辺を基準に全体を表示する
        imageView.center = CGPoint(x:screenWidth/2, y:screenHeight/2) // 画像の中心をスクリーンの中心位置に設定

        parentView.addSubview(imageView)
        parentView.sendSubview(toBack: imageView)
    }


ご親切にコードでもアドバイスをいただいておりますがどうしても、
横長の画像を出力する際にUIViewの縦の比率に対して画像の縦の長さに収まらずにいます。(ぴったりしない)

よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+2

横長画像で縦が短辺であれば、

imageView.contentMode = .scaleAspectFill

あるいは Content Mode を Aspect Fill。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/09/21 09:30

    imageView.clipsToBounds = true(あるいはClip to Boundsにチェック)しないとハミ出した部分が表示されちゃいますね。

    キャンセル

  • 2018/09/21 11:15

    あ、画面の幅いっぱいかつ縦長のUIImageViewで、さらに横長の画像を出す前提だと思っていました、、

    キャンセル

  • 2018/09/21 11:48

    確かに画面幅一杯ならハミ出しませんね‥。まぁclipsToBoundsは覚えていてもいいかと。(自己フォローw)

    キャンセル

  • 2018/09/21 13:51

    念のため、Aspect FillとAspect Fitでは挙動が変わります。

    キャンセル

+2

daisuke7さんとfuzzballさんの回答をコードにしたものが以下のものです。
fuzzballさんのおっしゃているclipsToBounds(勉強になりました)が分かる様に横幅を空けています。
画像は、Ryoma.pngにして、Assets.xcassetsに入れました。

import UIKit

let devWidth  = UIScreen.main.bounds.size.width
let devHeight = UIScreen.main.bounds.size.height

class ViewController: UIViewController {

    var myImageView : UIImageView!
    var myImage : UIImage!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        myImageView = UIImageView()
        myImageView.frame = CGRect(x: 20.0, y: 20.0, width: devWidth - 40.0, height: devHeight - 40.0)
        myImageView.image = UIImage(named: "Ryoma")
        myImageView.contentMode = .scaleAspectFill
        myImageView.clipsToBounds = true        
        self.view.addSubview(myImageView)
    }
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/09/21 16:07

    コードで解りやすく記述していただき、有難すぎて普通に感動しました!
    ありがとうございます!

    キャンセル

checkベストアンサー

+1

追記されたコードを見たところ、createImageViewメソッドのコメントに丁寧に

//画像の全体が把握できるように、画像本体(UIImage)の幅がスクリーンの幅よりも大きい時は、画像を画面の幅に合わせたUIImageViewとして表示するという処理を施す関数


と説明していますよね。
この通り動作するなら、UIImageViewのサイズは画面の横幅にあわせたサイズに調整されるので、Aspect FillにしようがAspect Fitにしようが関係なく画面の横幅に合わせた形で画像全体が表示されると思います。
このような処理をわざわざ自分で書いておいて、画面の高さいっぱいに画像が表示されるわけないです。

おそらく、このコードの意図は画面の横幅にあったサイズで画像全体を初期表示し、ピンチイン・ピンチアウトの操作で画像を拡大/縮小表示できるようにするつもりなのだと思います(コメントでも説明されている通り、画像の全体が把握できるように最初は画像全体を表示するのが適切だと私も思います)。

その初期表示を画面の高さに合わせた形で画面全体に表示するよう変更したいのなら、createImageViewメソッドの処理でUIImageViewのサイズを画面の横幅に合わせたサイズに調整しているのを画面の高さに合わせたサイズに調整するよう修正すればいいと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/09/22 16:56

    大変勉強になりました!
    ありがとうございます!

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 90.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • Swift

    9413questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています