Swift: невозможно центрировать ImageView на ScrollView - PullRequest
0 голосов
/ 16 марта 2019

Я пытаюсь отобразить imageView в центре по осям X и Y на scrollView, хорошо вписываясь в ширину устройства, когда я запускаю приложение.Я также хотел бы панорамировать и увеличить imageView.Я перепробовал почти все решения, которые были размещены на SO, а также следовал этому учебнику , но каким-то образом это просто не решило мою проблему.Изображение генерируется из PDF.

Я делаю макет программно.Моя реализация пока:

let scrollView: UIScrollView = {
    let sv = UIScrollView()
    sv.translatesAutoresizingMaskIntoConstraints = false
    sv.backgroundColor = .lightGray
    return sv
}()

let imageView: UIImageView = {
    let iv = UIImageView()
    iv.translatesAutoresizingMaskIntoConstraints = false
    iv.contentMode = .scaleAspectFill
    return iv
}()

override func viewDidLoad() {
    super.viewDidLoad()
    scrollView.delegate = self

    view.addSubview(scrollView)
    scrollView.addSubview(imageView)

    NSLayoutConstraint.activate([
        scrollView.topAnchor.constraint(equalTo: view.topAnchor),
        scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
        scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
        scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),

        imageView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 10),
        imageView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 10),
        imageView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -10),
        imageView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -10),

        ])

    imageView.image = obtainThumbnail()
}

fileprivate func updateMinZoomScaleForSize(_ size: CGSize) {
    let widthScale = size.width / imageView.bounds.width
    let heightScale = size.height / imageView.bounds.height
    let minScale = min(widthScale, heightScale)

    scrollView.minimumZoomScale = minScale
    scrollView.zoomScale = minScale
}

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()
    updateMinZoomScaleForSize(view.bounds.size)
}

func obtainThumbnail() -> UIImage? {
    guard let url = Bundle.main.url(forResource: "drawings", withExtension: "pdf") else {return nil}

    guard
        let data = try? Data(contentsOf: url),
        let page = PDFDocument(data: data)?.page(at: 0) else {
            return nil
    }

    let pageSize = page.bounds(for: .mediaBox)
    return page.thumbnail(of: CGSize(width: pageSize.width, height: pageSize.height), for: .mediaBox)
}

func viewForZooming(in scrollView: UIScrollView) -> UIView? {
    return imageView
}

Это мои желаемые результаты при запуске приложения.enter image description here

И это результаты, когда я сейчас запускаю приложение, перегружен.enter image description here

Кто-нибудь посоветует, что мне не хватает?

Ответы [ 2 ]

0 голосов
/ 16 марта 2019

Чтобы это работало хорошо, есть два места, которые нужно исправить:

  override func viewDidLoad() {
    super.viewDidLoad()
    scrollView.delegate = self

    view.addSubview(scrollView)
    scrollView.addSubview(imageView)

    NSLayoutConstraint.activate([

        scrollView.topAnchor.constraint(equalTo: view.topAnchor),
        scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),

       //First place.
       // scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
       // scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
        scrollView.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 0.0),
        scrollView.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: 0.0),



        imageView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 10),
        imageView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 10),
        imageView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -10),
        imageView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: -10),


        ])

    imageView.backgroundColor = UIColor.red
    imageView.image = UIImage.init(named: "temp2.png")
     //second place.
    imageView.sizeToFit()

Надеюсь, что это хорошо решило вашу проблему.

Если вам нужен вид посередине, попробуйтеследующий метод:

let scrollView: UIScrollView = {
    let sv = UIScrollView()
    sv.translatesAutoresizingMaskIntoConstraints = false
    sv.backgroundColor = .lightGray
  sv.contentMode = .center

 return sv
}()

 let imageView: UIImageView = {
    let iv = UIImageView()
    iv.translatesAutoresizingMaskIntoConstraints = true
    iv.contentMode = .scaleAspectFill
    return iv
}()

override func viewDidLoad() {
    super.viewDidLoad()
    scrollView.delegate = self

    view.addSubview(scrollView)
    scrollView.addSubview(imageView)



    NSLayoutConstraint.activate([


     scrollView.centerYAnchor.constraint(equalTo: view.centerYAnchor ),

    scrollView.centerXAnchor.constraint(equalTo: view.centerXAnchor ),


        scrollView.contentLayoutGuide.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor),
   scrollView.contentLayoutGuide.centerYAnchor.constraint(equalTo: scrollView.centerYAnchor),


        ])

    imageView.backgroundColor = UIColor.red
    imageView.image = UIImage.init(named: "temp2.png")
    imageView.sizeToFit()
    updateMinZoomScaleForSize(view.bounds.size)


}


var constantHeight : CGFloat{

    return  min(view.bounds.height, imageView.bounds.height *  scrollView.zoomScale)
}
var constantWidth : CGFloat{
    return min( view.bounds.width, imageView.bounds.width *  scrollView.zoomScale)
}

    lazy var constraintHeight: NSLayoutConstraint = {

     return      scrollView.contentLayoutGuide.heightAnchor.constraint(equalToConstant: constantHeight)

}()

    lazy  var constraintWeight: NSLayoutConstraint = {
    return
        scrollView.contentLayoutGuide.widthAnchor.constraint(equalToConstant: constantWidth)

}()



fileprivate func updateMinZoomScaleForSize(_ size: CGSize) {

    let widthScale = size.width / imageView.bounds.width
    let heightScale = size.height / imageView.bounds.height
    let minScale = min(widthScale, heightScale)

    imageView.frame = CGRect.init(x: 0, y: 0, width: minScale * imageView.bounds.width, height: minScale*imageView.bounds.height)


    scrollView.maximumZoomScale = 10.0
    scrollView.zoomScale = 1.0



    constraintHeight.isActive = true
  constraintWeight.isActive = true


}




func scrollViewDidEndZooming(_ scrollView: UIScrollView, with view: UIView?, atScale scale: CGFloat){

    constraintHeight.constant = constantHeight
    constraintWeight.constant  = constantWidth
    scrollView.clipsToBounds = true

}


func scrollViewWillBeginZooming(_ scrollView: UIScrollView, with view: UIView?) {
   scrollView.clipsToBounds = false
}


func viewForZooming(in scrollView: UIScrollView) -> UIView? {
    return imageView
}
0 голосов
/ 16 марта 2019

Я думаю, что представления загружаются лениво за UIViewController с, поэтому выполнение вычислений позже в жизненном цикле пользовательского интерфейса должно решить проблему. Удаление звонка в viewWillLayoutSubviews и использование вместо него:

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

    updateMinZoomScaleForSize(view.bounds.size)
}

кажется, работает.

...