UIPageViewController в UIScrollView отображается в полноэкранном режиме, даже если установлен CGRect - возвращается к правильным значениям кадра, как только пользователь прокручивает - PullRequest
0 голосов
/ 06 марта 2020

У меня есть UIPageViewController с именем SwipingPhotosController , где пользователь проводит пальцем по горизонтали для просмотра изображений. Я реализовал этот SwipingPhotosController в UIScrollView , задав ему значения CGRect . Затем я пишу функцию, которая в основном делает эффект растянутого заголовка увеличения и уменьшения при прокрутке пользователя вверх или вниз.

Все работает, за исключением того, что когда я пытался добавить еще один вид под SwipingPhotosController , как только контроллер загружается, изображение появляется во весь экран . Как только я слегка прокручиваю, все возвращается в точное положение.

Это то, что я получаю, когда нажимаю запустить в симуляторе - полноэкранный контроллер просмотра страниц:

enter image description here

Здесь представление возвращается в нормальное состояние, как только я слегка прокручиваю

enter image description here

Примечание: эта ошибка возникает только когда я добавляю nameLabel под imageView (swipingPhotosController.view)

class ProfileController: UIViewController, UIScrollViewDelegate {

    var user: User! {
        didSet{
            swipingPhotosController.user = user
        }
    }

    lazy var scrollProfileView: UIScrollView = {
        let sv = UIScrollView()
        sv.delegate = self
        sv.backgroundColor = TDGSettings
        sv.alwaysBounceVertical = true
        sv.contentInsetAdjustmentBehavior = .never
        return sv
    }()

    let nameLabel: UILabel = {
        let label = UILabel()
        label.font = .systemFont(ofSize: 12, weight: .bold)
        label.textColor = .white
        label.numberOfLines = 2
        label.textAlignment = .left
        return label
    }()

    let swipingPhotosController = SwipingPhotosController(transitionStyle: .scroll, navigationOrientation: .horizontal)

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = TDGSettings
        setupViews()
    }

    fileprivate func setupViews() {
        view.addSubview(scrollProfileView)
        scrollProfileView.fillSuperview()

        let imageView = swipingPhotosController.view!
        scrollProfileView.addSubview(imageView)

        let blurEffect = UIBlurEffect(style: .systemThinMaterialDark)
        let visualEffectView = UIVisualEffectView(effect: blurEffect)
        view.addSubview(visualEffectView)
        visualEffectView.anchor(top: view.topAnchor, leading: view.leadingAnchor, bottom: view.safeAreaLayoutGuide.topAnchor, trailing: view.trailingAnchor)

        scrollProfileView.addSubview(nameLabel)
        nameLabel.anchor(top: imageView.bottomAnchor, leading: view.leadingAnchor, bottom: nil, trailing: view.trailingAnchor, padding: .init(top: 16, left: 16, bottom: 0, right: 16))
        nameLabel.text = "First Name"
    }

    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        let imageView = swipingPhotosController.view!
        imageView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.width)
    }

    //STRETCHY HEADER EFFECT
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        let changeY = -scrollView.contentOffset.y
        var width = view.frame.width + changeY * 2
        width = max(view.frame.width, width)
        let imageView = swipingPhotosController.view!
        imageView.frame = CGRect(x: min(0, -changeY), y: min(0, -changeY), width: width, height: width)
    }
}

По запросу добавлен код для SwipingPhotosController

import Foundation
import LBTATools

class SwipingPhotosController: UIPageViewController, UIPageViewControllerDataSource, UIPageViewControllerDelegate {

    var user: User! {
        didSet{
            controllers = user.swipingUrls.map({ (url) -> UIViewController in
                let photoController = PhotosController(imageUrl: url)
                return photoController
            })
            setViewControllers([controllers.first!], direction: .forward, animated: false, completion: nil)
        }
    }
    var controllers = [UIViewController]()

    override func viewDidLoad() {
        super.viewDidLoad()
        dataSource = self
        delegate = self
    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
        let index = self.controllers.firstIndex(where: {$0 == viewController}) ?? 0
        if index == 0 {return nil}
        return controllers[index - 1]
    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
        let index = self.controllers.firstIndex(where: {$0 == viewController}) ?? 0
        if index == controllers.count - 1 {return nil}
        return controllers[index + 1]
    }
}


class PhotosController: UIViewController {

    let imageView = UIImageView()

    init(imageUrl: String) {
        if let url = URL(string: imageUrl){
            imageView.sd_setImage(with: url)
        }
        super.init(nibName: nil, bundle: nil)
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        imageView.contentMode = .scaleAspectFill
        view.addSubview(imageView)
        imageView.contentMode = .scaleAspectFill
        imageView.clipsToBounds = true
        imageView.fillSuperview()
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

1 Ответ

0 голосов
/ 07 марта 2020

Проблема в том, что вы устанавливаете кадр swipingPhotosController в viewWillLayoutSubviews() ---, но виды еще не были размечены.

Это необходимо сделать в viewDidLayoutSubviews() ( сделал не будет ).

Однако viewDidLayoutSubviews() вызывается много раз, особенно если вы меняете кадр снова в scrollViewDidScroll().

Итак, вам нужно установить флаг, чтобы установить кадр только в viewDidLayoutSubviews() один раз (или снова, если кадр scrollView изменился).

Не будучи уверенным, как или когда вы устанавливали свойства SwipingPhotosController, я сделал это таким образом, чтобы проверить:

// add a class property
var savedScrollViewWidth: CGFloat = 0.0

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    if scrollProfileView.frame.width != savedScrollViewWidth {
        savedScrollViewWidth = scrollProfileView.frame.width
        let imageView = swipingPhotosController.view!
        imageView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.width)
    }

}

Проверьте, правильно ли работает ваш макет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...