Может кто-нибудь сказать мне, как я могу имитировать нижний лист в новом приложении Карт в iOS 10?
В Android вы можете использовать функцию, BottomSheet
имитирующую это поведение, но я не смог найти ничего подобного для iOS.
Это простой вид прокрутки с вложенным содержимым, так что панель поиска находится внизу?
Я довольно новичок в программировании на iOS, поэтому, если кто-то может помочь мне создать этот макет, это будет высоко оценено.
Вот что я имею в виду под «нижним листом»:
Ответы:
Я не знаю, как именно нижний лист нового приложения Карт реагирует на взаимодействие с пользователем. Но вы можете создать собственный вид, похожий на тот, что на скриншотах, и добавить его в основной вид.
Я полагаю, вы знаете, как:
1 - создавать контроллеры представления либо раскадровками, либо с использованием файлов XIB.
2- используйте GoogleMaps или Apple MapKit.
пример
1- Создайте 2 контроллера вида, например, MapViewController и BottomSheetViewController . Первый контроллер будет размещать карту, а второй - сам нижний лист.
Настроить MapViewController
Создайте метод для добавления вида нижнего листа.
И вызвать его в методе viewDidAppear:
Настроить BottomSheetViewController
1) Подготовить фон
Создать метод для добавления эффектов размытия и вибрации
вызовите этот метод в вашем viewWillAppear
Убедитесь, что цвет фона вашего контроллера - clearColor.
2) Анимированный вид нижнего листа
3) Измените ваш XIB, как вы хотите.
4) Добавьте Pan Gesture Recognizer к вашему виду.
В вашем методе viewDidLoad добавьте UIPanGestureRecognizer.
И реализуйте свое поведение жеста:
Прокручиваемый нижний лист:
Если ваш пользовательский вид представляет собой вид с прокруткой или любой другой вид, который наследуется, у вас есть два варианта:
Первый:
Создайте представление с представлением заголовка и добавьте panGesture в заголовок. (плохой пользовательский опыт) .
Во-вторых:
1 - Добавьте panGesture к виду нижнего листа.
2 - Реализуйте UIGestureRecognizerDelegate и установите делегат panGesture на контроллер.
3- Реализовать функцию requireRecognizeSimuallyWith делегата и отключить свойство scrollView isScrollEnabled в двух случаях:
В противном случае включите прокрутку.
НОТА
В случае, если вы установите .allowUserInteraction в качестве опции анимации, как в примере проекта, вам нужно включить прокрутку при закрытии завершения анимации, если пользователь прокручивает вверх.
Пример проекта
Я создал пример проекта с большим количеством опций в этом репо, который может дать вам лучшее представление о том, как настроить поток.
В демонстрационной версии функция addBottomSheetView () контролирует, какой вид следует использовать в качестве нижнего листа.
Пример проекта Скриншоты
- Частичный вид
- Полный обзор
- прокручиваемый вид
источник
Я выпустил библиотеку на основе моего ответа ниже.
Он имитирует наложение приложения «Ярлыки». Смотрите эту статью для деталей.
Основным компонентом библиотеки является
OverlayContainerViewController
. Он определяет область, в которой контроллер представления можно перетаскивать вверх и вниз, скрывая или раскрывая содержимое под ним.Реализуйте,
OverlayContainerViewControllerDelegate
чтобы указать желаемое количество меток:Предыдущий ответ
Я думаю, что есть важный момент, который не рассматривается в предлагаемых решениях: переход между прокруткой и переводом.
В Картах, как вы могли заметить, когда таблица достигает
contentOffset.y == 0
, нижний лист либо сдвигается вверх, либо опускается.Суть хитрая, потому что мы не можем просто включить / отключить прокрутку, когда наш жест панорамирования начинает перевод. Это остановит прокрутку, пока не начнется новое касание. Это имеет место в большинстве предлагаемых здесь решений.
Вот моя попытка реализовать это движение.
Начальная точка: приложение «Карты»
Для того, чтобы начать наше исследование, давайте визуализировать иерархию вида Карт (начало карты на тренажере и выберите
Debug
>Attach to process by PID or Name
>Maps
в Xcode 9).Это не говорит, как работает движение, но оно помогло мне понять логику этого. Вы можете поиграть с lldb и отладчиком иерархии представлений.
Наш вид контроллеров стеков
Давайте создадим базовую версию архитектуры Maps ViewController.
Мы начнем с
BackgroundViewController
(наш вид карты):Мы помещаем tableView в выделенный
UIViewController
:Теперь нам нужен VC, чтобы встроить оверлей и управлять его переводом. Чтобы упростить задачу, мы считаем, что она может перевести оверлей из одной статической точки
OverlayPosition.maximum
в другуюOverlayPosition.minimum
.На данный момент у него есть только один публичный метод для анимации изменения позиции и прозрачный вид:
Наконец, нам нужен ViewController для встраивания всего:
В нашем AppDelegate наша последовательность запуска выглядит следующим образом:
Сложность перевода наложения
Теперь, как перевести наш оверлей?
В большинстве предлагаемых решений используется специальный распознаватель жестов панорамирования, но у нас уже есть один: жест панорамирования представления таблицы. Более того, нам нужно синхронизировать прокрутку и перевод, а также
UIScrollViewDelegate
все необходимые события!Наивная реализация будет использовать второй панорамирование Gesture и попытаться сбросить
contentOffset
представление таблицы при выполнении перевода:Но это не работает. TableView обновляет его,
contentOffset
когда срабатывает его собственное действие распознавателя жестов панорамирования или когда вызывается его обратный вызов displayLink. Нет никаких шансов, что наш распознаватель сработает сразу после того, как они успешно переопределятcontentOffset
. Наш единственный шанс - либо принять участие в фазе макета (путем переопределенияlayoutSubviews
вызовов представления прокрутки в каждом кадре представления прокрутки), либо ответить наdidScroll
метод делегата, вызываемого каждый раз, когдаcontentOffset
изменяется. Давайте попробуем это.Реализация перевода
Мы добавляем делегата к нашему
OverlayVC
для отправки событий scrollview в наш обработчик переводаOverlayContainerViewController
:В нашем контейнере мы отслеживаем перевод, используя перечисление:
Расчет текущей позиции выглядит так:
Нам нужно 3 метода для обработки перевода:
Первый говорит нам, если нам нужно начать перевод.
Второй выполняет перевод. Он использует
translation(in:)
метод панорамирования жеста scrollView.Третий анимирует конец перевода, когда пользователь отпускает палец. Мы рассчитываем позицию, используя скорость и текущую позицию вида.
Реализация делегата нашего оверлея выглядит просто так:
Последняя проблема: отправка штрихов оверлейного контейнера
Перевод теперь довольно эффективен. Но есть еще последняя проблема: штрихи не передаются в фоновом режиме. Все они перехвачены видом наложенного контейнера. Мы не можем установить ,
isUserInteractionEnabled
чтобы ,false
потому что она будет также отключить взаимодействие в нашей точки зрения таблицы. Это решение широко используется в приложении «Карты»PassThroughView
:Он удаляет себя из цепочки респондента.
В
OverlayContainerViewController
:результат
Вот результат:
Вы можете найти код здесь .
Пожалуйста, если вы видите какие-либо ошибки, дайте мне знать! Обратите внимание, что ваша реализация может, конечно, использовать второй жест панорамирования, особенно если вы добавляете заголовок в оверлей.
Обновление 23/08/18
Мы можем заменить
scrollViewDidEndDragging
сwillEndScrollingWithVelocity
чемenabling
/disabling
свиткой , когда концы пользователя перетаскивания:Мы можем использовать весеннюю анимацию и разрешить взаимодействие с пользователем во время анимации, чтобы улучшить движение:
источник
UIViewPropertyAnimator
(который имеет возможность приостановки), а затем использоватьfractionComplete
свойство для выполнения очистки.translateView(following:)
методе вы вычисляете высоту на основе перевода, но она может начинаться с значения, отличного от 0,0 (например, представление таблицы немного прокручивается, а наложение увеличивается при начале перетаскивания) . Это приведет к начальному прыжку. Вы можете решить эту проблему с помощьюscrollViewWillBeginDragging
обратного вызова, в котором вы запомните инициалcontentOffset
табличного представления и будете использовать его вtranslateView(following:)
вычислениях.csrutil disable && reboot
. После этого вы получите все полномочия, которые обычно дает root, в том числе возможность подключения к процессу Apple.Попробуйте шкив :
https://github.com/52inc/Pulley
источник
Вы можете попробовать мой ответ https://github.com/SCENEE/FloatingPanel . Он предоставляет контроллер представления контейнера для отображения интерфейса «нижнего листа».
Он прост в использовании, и вы не возражаете против любой обработки распознавания жестов! Также вы можете отслеживать вид прокрутки (или родственный вид) на нижнем листе, если это необходимо.
Это простой пример. Обратите внимание, что вам необходимо подготовить контроллер представления для отображения вашего контента на нижнем листе.
Вот еще один пример кода для отображения нижнего листа для поиска местоположения, такого как Apple Maps.
источник
Я написал свою собственную библиотеку для достижения желаемого поведения в приложении ios Maps. Это протоколно-ориентированное решение. Поэтому вам не нужно наследовать какой-либо базовый класс, вместо этого создайте контроллер листа и настройте его по своему усмотрению. Он также поддерживает внутреннюю навигацию / презентацию с или без UINavigationController.
Смотрите ссылку ниже для более подробной информации.
https://github.com/OfTheWolf/UBottomSheet
источник
Недавно я создал компонент, называемый
SwipeableView
подклассомUIView
, написанный на Swift 5.1. Он поддерживает все 4 направления, имеет несколько параметров настройки и может анимировать и интерполировать различные атрибуты и элементы (такие как ограничения макета, цвет фона / оттенок, аффинное преобразование, альфа-канал и центр просмотра, все они демонстрируются в соответствующем демонстрационном случае). Он также поддерживает координацию прокрутки с видом внутренней прокрутки, если он установлен или определяется автоматически. Должно быть довольно простым и понятным в использовании (я надеюсь 🙂)Ссылка на https://github.com/LucaIaco/SwipeableView
подтверждение концепции:
Надеюсь, поможет
источник
Может быть, вы можете попробовать мой ответ https://github.com/AnYuan/AYPannel , вдохновленный Pulley. Плавный переход от перемещения ящика к прокрутке списка. Я добавил жест панорамирования в представлении прокрутки контейнера и установил shouldRecognizeSim одновременноouslyWithGestureRecognizer для возврата YES. Более подробно в моей ссылке выше. Желание помочь.
источник