Привет. В следующей серии руководств я покажу вам, как реализовать каждую функцию экрана профиля Twitter. Это будет сделано без сторонних фреймворков, и мы не будем манипулировать фреймом UIView. Мы будем использовать исключительно Autolayout. Первое, что мы сделаем, это создадим эластичный заголовок.

Примечание. В этом руководстве мы будем использовать UIScrollView вместо UITableView, но общую стратегию, которую я продемонстрирую сегодня, легко перенести на UITableView / UICollectionView / Anything, являющийся подклассом UIScrollView.

Необходимые знания:

Основные концепции iOS (жизненный цикл UIViewController, UIViews и т. Д.)

Использование Autolayout с UIScrollViews

Стратегия:

  1. Сначала мы настроим автоматическое размещение для нашего UIScrollView
  2. Затем внутри представления содержимого нашего scrollview мы установим ограничения автоматического раскладки для изображения. Ограничения по верхнему краю и высоте нашего изображения являются ключевыми для эффекта растягивания.
  3. Наш контроллер представления расширит UIScrollViewDelegate и реализует функцию scrollviewDidScroll ()
  4. Внутри нашей функции scrollviewDidScroll () мы будем отслеживать положение прокрутки по оси y.
  5. Если мы прокручиваем вверх (опускаемся) мимо начальной позиции прокрутки, нам нужно сделать 2 вещи. Сначала обновите верхнее ограничение просмотра изображения, чтобы оно было значением вертикального положения scrollview. Затем увеличьте высоту, добавив разницу между нашим смещением содержимого и начальным смещением содержимого по вертикали (которое равно 0).
  6. Почти отпраздновать. Если оставить проект без изменений, высота увеличится, но ширина не изменится вместе с высотой. Чтобы ширина расширялась вместе с высотой, не забудьте изменить режим содержимого представления изображения на заливку по сторонам вместо заливки по шкале.

Если у вас нет опыта использования Autolayout с UIScrollViews, вот отличная статья: https://www.natashatherobot.com/ios-autolayout-scrollview/

Создайте быстрый проект по указанной выше ссылке, а затем вернитесь к этому.

ОК, приступим.

Вы можете скачать мой стартовый проект здесь: https://github.com/EddieCurio/StretchHeaderMedium

Также, если вы застряли на какой-либо из частей, вы можете переключиться на готовую ветку.

ветви

Мастер - Ничего не сделал.

часть 1 - Завершение шага 1

часть 2 - Завершение шага 2

part6 - Завершение шага 6

Каждая часть разделена на разные ветки на всякий случай, если вы заблудитесь.

Шаг 1а. Загрузите стартовый проект в Xcode.

Обратите внимание, что этот проект практически пуст, за исключением фотографии волны.

Шаг 1б. Настройте автоматическое размещение для прокрутки.

  1. Сначала добавьте изображение прокрутки в сцену UIViewController в раскадровке.

2.) Мы хотим, чтобы представление прокрутки занимало весь экран, поэтому мы будем прикреплять края к супервизору (вы можете просто прикрепить его к безопасной области, это просто зависит от вашего варианта использования). Мы увидим, почему мы прикрепляем к родительский вид вместо безопасной области в более позднем руководстве.

3.) Определите представление содержимого и установите ограничения представления содержимого для представления прокрутки.

Итак, мы создаем представление содержимого и помещаем его в UIScrollView. Затем мы создаем ограничение EQUAL WIDTH и EQUAL HEIGHT между представлением содержимого и родительским представлением прокрутки НЕ SCROLLVIEW

Если вы случайно закрепите высоту в scrollview, scrollview запутается и не узнает, как рассчитать высоту своего содержимого.

Прочтите статью, о которой я упоминал ранее, для получения дополнительной информации. Но основная идея заключается в том, что вам нужно сделать высоту представления содержимого постоянной или зависимой от чего-то другого, кроме самого scrollview.

Затем мы можем просто прикрепить края представления содержимого к краям представления прокрутки.

Шаг 2. Добавьте UIImageView к просмотру прокрутки и добавьте ограничения.

1.) Добавьте ограничения Top, Left, Right и Height (128 на сегодня, но для ваших приложений это может быть все, что вы хотите) для просмотра изображения и после размещения в нашем представлении содержимого в раскадровке.

Шаг 3. Создайте выходы с учетом ограничений просмотра изображений.

Мы будем манипулировать ограничением по высоте и верхнему краю изображения, основываясь на свойстве вертикального смещения содержимого scrollview, поэтому нам нужны ссылки на них в нашем коде.

Шаг 4. Создайте торговые точки с помощью нашего scrollview.

Нам также понадобится ссылка на наш scrollview, чтобы сделать наш viewcontroller делегатом протокола UIScrollViewDelegate. Это позволит нам реализовать функцию scrollviewDidScroll ()

Мы также хотим реализовать протокол UIScrollViewDelegate и сделать наш класс контроллера представления делегатом для нашего представления прокрутки, которое мы настроили в раскадровке.

На этом этапе вы должны запустить приложение.

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

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

Шаг 5 Реализуйте логику эластичного заголовка

Первое, что мы хотим сделать, это если мы прокручиваем слишком высоко, тогда мы хотим, чтобы изображение оставалось наверху. Итак, давайте сначала сделаем это.

Сначала давайте определим, что такое «слишком высокий». Мы говорим, что зашли «слишком высоко», если прокручиваем страницу выше стандартной конфигурации прокрутки. Это происходит только тогда, когда мы прокручиваем над вертикальным смещением содержимого нашего прокрутки, равным 0. Поэтому, когда мы прокручиваем выше 0, мы «слишком высоко» и должны скорректировать ограничения просмотра изображения. Эту логику легко перевести в код.

Шаг 5. Сделайте так, чтобы верхняя часть окна просмотра изображения прилипала к «новой вершине» при прокрутке вверх.

В вашей функции scrollViewDidScroll () нам нужно определить, когда мы зашли «слишком высоко»

Для этого мы добавляем следующий код

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    let offset = scrollView.contentOffset.y
    if offset < 0{ //Whenever we go too high run this code block 
     //Make imageview sticky
    }
}

Что нам теперь делать после того, как мы зайдем слишком высоко?

Делаем верхнюю палку. Как сделать верхнюю палку? Что ж, нам нужно вычислить, что считается «новой вершиной» экрана. Оказывается, это просто значение y для смещения содержимого. Итак, теперь у нас должно быть….

func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offset = scrollView.contentOffset.y
let defaultTop = CGFloat(0)
// If we have not scrolled too high then stick to default y pos
var currentTop = defaultTop 
if offset < 0{ //Whenever we go too high run this code block 
     //The new top (y position) of the imageview 
     currentTop = offset
}

imageViewTop.constant = currentTop
}

После добавления этого кода запустите приложение, оно должно выглядеть примерно так.

Может показаться, что он ничего не делает, но сравните это с последним запуском кода, и когда мы прокручиваем вверх, мы больше не видим белого промежутка над изображением. Другими словами, это работает!

Шаг 6. Сделайте так, чтобы изображение «расширялось», когда мы прокручиваем слишком высоко.

Мы хотим, чтобы изображение расширялось пропорционально тому, на сколько прокручиваемое изображение переместилось вверх. Скажем, мы перемещаемся на 10 единиц выше нашей базовой линии 0. Затем мы хотим добавить 10 единиц к высоте нашего изображения.

Тогда как мы можем вычислить количество перемещенных единиц выше 0?

Просто снова используйте смещение содержимого. Если мы поднимемся на 30 единиц выше 0, то значение вертикального смещения содержимого будет равно -30. Поэтому мы просто добавляем абсолютное значение смещения содержимого к ограничению высоты.

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

Эту логику снова легко перевести в код.

В вашем контроллере представления добавьте переменную

var originalHeight: CGFloat!

и в viewDidLoad () добавьте следующий код

func viewDidLoad(){
    ...
   originalHeight = imageViewHeight.constant
}

поэтому мы сразу фиксируем исходное значение ограничения высоты.

Затем мы добавляем следующий код в нашу функцию scrollviewDidScroll ()

func scrollViewDidScroll(_ scrollView: UIScrollView){
  ...
  
   if offset < 0 {
    ...
    //Original height + abs(offset)
    imageViewHeight.constant = originalHeight - offset
    ...
   }else { //We are finished scrolling up 
     //Done streching out the image
     imageViewHeight.constant = originalHeight
   }

}

Запустите свой код, и вы должны увидеть следующее.

Мы почти на месте. Мы также хотим, чтобы ширина масштабировалась вместе с высотой. Если мы изменим режим содержимого изображения на аспектную заливку вместо масштабной заливки, то наше приложение должно выглядеть так.

И мы закончили.