Простое Интерактивное Всплывающее Окно Для Ios — Руководство По Swiftui

Один из лучших способов изучить SwiftUI (как и большинство технологий) — реализовать что-нибудь маленькое и полезное.

Всплывающее окно является отличным вариантом — это один из самых популярных инструментов интерфейса, который часто приходится настраивать, если родной вариант неудовлетворительный по внешнему виду или функциональности.

В этом уроке мы создадим минимальное всплывающее окно в SwiftUI с нуля.

В результате мы получим работающий компонент пользовательского интерфейса, который вы сможете реализовать в своем приложении SwiftUI или продолжить его настройку и улучшение.

Вот как это будет выглядеть:

Простое интерактивное всплывающее окно для iOS — руководство по SwiftUI



Выбор API

Для начала давайте определимся с функционалом всплывающего окна, которое мы хотим реализовать.

Это будет элемент, который будет отображаться при нажатии кнопки.

Он просто отобразит метку.

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

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

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

Такой подход позволит вам сразу понять, как будет удобнее использовать компонент в вашем коде.

  
  
  
  
  
   

struct ContentView : View { @State var showingPopup = false // 1 var body: some View { ZStack { Color.red.opacity(0.2) Button("Push me") { showingPopup = true // 2 } } .

popup(isPresented: $showingPopup) { // 3 ZStack { // 4 Color.blue.frame(width: 200, height: 100) Text("Popup!") } } } }

Вот что делает этот простой пример:
  1. Мы добавляем всплывающее окно в качестве модификатора к нашему элементу, передавая @Binding показ всплывающего окна для управления состоянием внутри реализации самого элемента.

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

  2. Отдельная кнопка на экране будет изменять состояние переменной showPopup.
  3. Мы добавляем всплывающее окно в качестве модификатора к нашему элементу, передавая @Binding показ всплывающего окна для управления состоянием внутри реализации самого элемента.

  4. Дизайн и содержимое всплывающего окна также передаются в качестве параметра.

  5. Само всплывающее окно реализовано как Модификатор просмотра , как это принято в SwiftUI.
Теперь, когда у нас есть представление о желаемом интерфейсе и виде всплывающего окна, приступим к фактической реализации.

Реализация модификатора представления

extension View { public func popup<PopupContent: View>( isPresented: Binding<Bool>, view: @escaping () -> PopupContent) -> some View { self.modifier( Popup( isPresented: isPresented, view: view) ) } }

Этот фрагмент кода не требует пояснений — это определение модификатора всплывающего окна для представления.

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

Теперь мы можем перейти к самому интересному.



Реализация всплывающего элемента

Инициализатор и общедоступные переменные понятны — они уже были определены и объяснены, когда мы выбрали API:

public struct Popup<PopupContent>: ViewModifier where PopupContent: View { init(isPresented: Binding<Bool>, view: @escaping () -> PopupContent) { self._isPresented = isPresented self.view = view } /// Controls if the sheet should be presented or not @Binding var isPresented: Bool /// The content to present var view: () -> PopupContent

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

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



// MARK: - Private Properties /// The rect of the hosting controller @State private var presenterContentRect: CGRect = .

zero /// The rect of popup content @State private var sheetContentRect: CGRect = .

zero /// The offset when the popup is displayed private var displayedOffset: CGFloat { -presenterContentRect.midY + screenHeight/2 } /// The offset when the popup is hidden private var hiddenOffset: CGFloat { if presenterContentRect.isEmpty { return 1000 } return screenHeight - presenterContentRect.midY + sheetContentRect.height/2 + 5 } /// The current offset, based on the "presented" property private var currentOffset: CGFloat { return isPresented ? displayedOffset : hiddenOffset } private var screenWidth: CGFloat { UIScreen.main.bounds.size.width } private var screenHeight: CGFloat { UIScreen.main.bounds.size.height }

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

Сам лист делает почти то же самое — он считывает свой кадр, чтобы позиционировать видимое всплывающее окно пользовательского интерфейса, а также добавляет обработчик для удаления отображаемого всплывающего окна при нажатии и простую анимацию.

Ранее рассчитанное текущееСмещение :

// MARK: - Content Builders public func body(content: Content) -> some View { ZStack { content .

frameGetter($presenterContentRect) } .

overlay(sheet()) } func sheet() -> some View { ZStack { self.view() .

simultaneousGesture( TapGesture().

onEnded { dismiss() }) .

frameGetter($sheetContentRect) .

frame(width: screenWidth) .

offset(x: 0, y: currentOffset) .

animation(Animation.easeOut(duration: 0.3), value: currentOffset) } } private func dismiss() { isPresented = false }

Чтобы реализовать простую анимацию в SwiftUI, достаточно добавить однострочный модификатор, что мы и делаем в конце создания.

лист .

Естественно, его можно анимировать по вашему желанию — просто заменив окончательный размер и положение на экране, вы можете получить другой тип элемента пользовательского интерфейса (например, верхний или нижний тост).

Скорее всего, вы заметили модификатор FrameGetter. Это некрасивый, но необходимый метод получения фрейма в SwiftUI (по крайней мере, судя по документации, более удобного способа получения фрейма в SwiftUI у нас нет).

Надеемся, в будущем появится более удобный способ:

extension View { func frameGetter(_ frame: Binding<CGRect>) -> some View { modifier(FrameGetter(frame: frame)) } } struct FrameGetter: ViewModifier { @Binding var frame: CGRect func body(content: Content) -> some View { content .

background( GeometryReader { proxy -> AnyView in let rect = proxy.frame(in: .

global) // This avoids an infinite layout loop if rect.integral != self.frame.integral { DispatchQueue.main.async { self.frame = rect } } return AnyView(EmptyView()) }) } }

GeometryReader — это представление в SwiftUI, которое принимает координатное пространство в качестве параметра и предоставляет информацию о его размере содержимому (другими словами, именно то, что необходимо для получения данных о кадре).



Заключение

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

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

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

Он заметно сложнее из-за большего количества стилей всплывающих окон, расширенных параметров и обратных вызовов, а также поддержки нескольких платформ.

Код для отображения и добавления всплывающего окна идентичен приведенному выше.

Библиотека предоставляет как простые всплывающие окна:

Простое интерактивное всплывающее окно для iOS — руководство по SwiftUI

и более сложные пользовательские представления:

Простое интерактивное всплывающее окно для iOS — руководство по SwiftUI

Теги: #с открытым исходным кодом #Swift #swiftUI #switch #popup #popup

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.