Как сделать масштабированное изображение в Navigation Bar с большим Title

Введение

Команда Web Academy подготовила руководство, в котором показана реализация изображения, которое изменяет размер в соответствии с высотой Navigation Bar c большим Title. Демо можно увидеть выше.

Перейдем же прямо к кодингу.

Шаг 1. Создание изображения

Объявим property в класс

private let imageView = UIImageView(image: UIImage(named: image_name))

Примечание: Это также может быть UIButton или все, что является подклассом UIView

Шаг 2. Добавление констант

Ваш дизайн уникален: добавьте структуру Constants с вашими кастомными размерами и отступами. Просто скопируйте код (написанный ниже) в ваш класс и измените значения констант в соответствии с вашим дизайном:

/// WARNING: Change these constants according to your project’s design

private struct Const {

    /// Image height/width for Large NavBar state

    static let ImageSizeForLargeState: CGFloat = 40

    /// Margin from right anchor of safe area to right anchor of Image

    static let ImageRightMargin: CGFloat = 16

    /// Margin from bottom anchor of NavBar to bottom anchor of Image for Large NavBar state

    static let ImageBottomMarginForLargeState: CGFloat = 12

    /// Margin from bottom anchor of NavBar to bottom anchor of Image for Small NavBar state

    static let ImageBottomMarginForSmallState: CGFloat = 6

    /// Image height/width for Small NavBar state

    static let ImageSizeForSmallState: CGFloat = 32

    /// Height of NavBar for Small state. Usually it’s just 44

    static let NavBarHeightSmallState: CGFloat = 44

    /// Height of NavBar for Large state. Usually it’s just 96.5 but if you have a custom font for
the title, please make sure to edit this value since it changes the height for Large state of NavBar

    static let NavBarHeightLargeState: CGFloat = 96.5

}

Примечание: Я рекомендую прочитать описание констант

Визуализация констант:

a) Большой Navigation Bar

б) Малый Navigation Bar

Шаг 3. Первоначальная настройка вашего UI

Создайте метод начальной настройки вашего UI:

private func setupUI() {

    navigationController?.navigationBar.prefersLargeTitles = true

 

    title = “Large Title”

 

    // Initial setup for image for Large NavBar state since the the screen always has Large NavBar once it gets opened

    guard let navigationBar = self.navigationController?.navigationBar else { return }

    navigationBar.addSubview(imageView)

    imageView.layer.cornerRadius = Const.ImageSizeForLargeState / 2

    imageView.clipsToBounds = true

    imageView.translatesAutoresizingMaskIntoConstraints = false

    NSLayoutConstraint.activate([

        imageView.rightAnchor.constraint(equalTo: navigationBar.rightAnchor, constant: –Const.ImageRightMargin),

        imageView.bottomAnchor.constraint(equalTo: navigationBar.bottomAnchor, constant: –Const.ImageBottomMarginForLargeState),

        imageView.heightAnchor.constraint(equalToConstant: Const.ImageSizeForLargeState),

        imageView.widthAnchor.constraint(equalTo: imageView.heightAnchor)

        ])

}

Примечание: Не забудьте вызвать этот метод.

Веха #1:

Запустите проект и проверьте, нет ли ошибок в консоли, и отображается ли изображения правильно. Обратите внимание, что пока изображение не будет изменять размер.

Шаг 4. Метод изменения размера

Создайте метод, который будет изменять размер и перемещать изображение в Navigation Bar:

private func moveAndResizeImage(for height: CGFloat) {

    let coeff: CGFloat = {

        let delta = height – Const.NavBarHeightSmallState

        let heightDifferenceBetweenStates = (Const.NavBarHeightLargeState – Const.NavBarHeightSmallState)

        return delta / heightDifferenceBetweenStates

    }()

 

    let factor = Const.ImageSizeForSmallState / Const.ImageSizeForLargeState

 

    let scale: CGFloat = {

        let sizeAddendumFactor = coeff * (1.0 – factor)

        return min(1.0, sizeAddendumFactor + factor)

    }()

 

    // Value of difference between icons for large and small states

    let sizeDiff = Const.ImageSizeForLargeState * (1.0 – factor) // 8.0

    let yTranslation: CGFloat = {

        /// This value = 14. It equals to difference of 12 and 6 (bottom margin for large and small states). Also it adds 8.0 (size difference when the image gets smaller size)

        let maxYTranslation = Const.ImageBottomMarginForLargeState – Const.ImageBottomMarginForSmallState + sizeDiff

        return max(0, min(maxYTranslation, (maxYTranslation – coeff * (Const.ImageBottomMarginForSmallState + sizeDiff))))

    }()

 

    let xTranslation = max(0, sizeDiff – coeff * sizeDiff)

 

    imageView.transform = CGAffineTransform.identity

        .scaledBy(x: scale, y: scale)

        .translatedBy(x: xTranslation, y: yTranslation)

}

 

Коротко о том, как работает этот метод: размер изображения изменяется с помощью .scaledBy. А перемещение изображения, происходит с помощью .translatedBy, по таким правилам:

  • Чтобы правый отступ был всегда 16pt
  • Чтобы нижний отступ менялся c 6pt на 12pt

Шаг 5. Внедрение метода делегирования UIScrollView

Добавьте делегатский метод UIScrollView и вызовите метод с предыдущего шага:

override func scrollViewDidScroll(_ scrollView: UIScrollView) {

    guard let height = navigationController?.navigationBar.frame.height else { return }

    moveAndResizeImage(for: height)

}

 

Веха #2 (финальная):

Запустите приложение и проверьте правильно ли изменяется размер картинки при прокрутке вниз/вверх:

Шаг 6. Скрыть изображение (опционально)

Если вам нужно скрыть изображение из навигации, когда вы переходите на другой экран в стеке навигейшн контроллера, добавьте следующие методы:

 

override func viewWillDisappear(_ animated: Bool) {

    super.viewWillDisappear(animated)

    showImage(false)

}

 

override func viewWillAppear(_ animated: Bool) {

    super.viewWillAppear(animated)

    showImage(true)

}

 

/// Show or hide the image from NavBar while going to next screen or back to initial screen

///

/// – Parameter show: show or hide the image from NavBar

private func showImage(_ show: Bool) {

    UIView.animate(withDuration: 0.2) {

        self.imageView.alpha = show ? 1.0 : 0.0

    }

}

 

Шаг 7. Action при нажатии на изображение (опционально)

Если вы хотите выполнить какое-то действие при нажатии на картинку, следуйте этому ответу.

You are done ?

. . .

Автор статьи: Tung Fam

Полный проект на Github.

Оригинальная статья: How to build resizing Image in Navigation Bar with Large Title

1
0
SAVE