Разработка
Малоизвестные представления SwiftUI
Когда вы начали изучать swiftUI, вы могли столкнуться с большим количеством представлений, таких как:
- VStack, HStack, ZStack, ScrollView, Grid
- Также, возможно, GeometryReader, Lazy(V,H,Z) Stack.
Здесь я пытаюсь показать некоторые представления, которые в целом редко используются (если вы глубоко погружены в SwiftUI, то, возможно, уже знаете их).
AnyLayout
AnyLayout пригодится вам, когда вы захотите динамически переключаться между HStack и VStack во время выполнения программы.
struct AnyLayoutView: View { @State var dynamicLayout = true var body: some View { VStack(spacing:50) { let layout = dynamicLayout ? AnyLayout(HStackLayout()) : AnyLayout(VStackLayout()) layout { Text(/*@START_MENU_TOKEN@*/"Hello, World!"/*@END_MENU_TOKEN@*/) .modifier(CustomModifer()) Text("This is Custom layout") .font(.title) .foregroundStyle(Color.teal) } Button("Toggle Layout") { dynamicLayout.toggle() } } } }
Условие переключателя не обязательно должно быть bool с кнопкой, оно может быть любым, например:
- Ориентация устройства (Пейзаж/Портрет)
- Размер текста для доступности (XXL, XL)
- На основе счетчика и т.д.
ViewThatFits
ViewThatFits можно использовать в тех случаях, когда вам нужно отобразить различные представления, основываясь на наилучшем вписывании в рамки доступного устройства.
Это удобно, если вы настраиваете представление в зависимости от размера экрана.
ViewThatFits всегда:
- Начинает проверку с первого View и проверяет дальше
- Рендерит первое представление, которое подходит для контейнера
- Если ни один из них не подходит, рендерится последний вид
Совет
- Начинайте проверку от самого верхнего вида к самому нижнему (см. пример кода)
struct ViewThatFitExample: View { var body: some View { ViewThatFits { RoundedRectangle(cornerRadius: 15) .fill(Color.orange) .padding(10) .frame(width: 300, height: 1000) RoundedRectangle(cornerRadius: 15) .fill(Color.red) .padding(10) .frame(width: 300, height: 700) RoundedRectangle(cornerRadius: 15) .fill(Color.blue) .padding(10) .frame(width: 300, height: 300) } } }
ContentUnavailableView
ContentUnavailableView может быть использован для создания плейсхолдера или когда содержимое недоступно (как следует из названия), например:
- Когда список/таблица пуста
- Когда потерялась связь с сетью
- Когда возникла общая ошибка с приложением
- Или как обучающий View перед загрузкой контента
1. Основное представление недоступности:
struct ContentViewBasic: View { @State var isContentAvailable = false var sampleData: [String] = ["Available content one", "Available content two", "Available content three"] @State var contentData : [String] = ["Available content one", "Available content two", "Available content three"] var body: some View { NavigationStack { ForEach(contentData, id: \.self) { contact in Text(contact) } .navigationTitle("Some View") .padding(10) .navigationViewStyle(.columns) }.overlay { if isContentAvaliable { getUnavailableContent() } } Button(action: { contentData = isContentAvaliable ? sampleData : [] isContentAvaliable.toggle() }, label: { Text(!isContentAvaliable ? "Switch Content to zero" : "Add Content") .foregroundColor(.white) .frame(width: 200, height: 40) .background(Color.green) .cornerRadius(15) .padding() }) .frame(alignment: .bottom) } @ViewBuilder func getUnavailableContent() -> some View { ContentUnavailableView { Image(systemName: "text.page.slash") .font(.largeTitle) .foregroundStyle(.red) .symbolEffect(.wiggle.clockwise.wholeSymbol, options: .repeating) Text("No content here") } } }
В приведенном выше коде видно, что функция getUnavailableContent()
вызывается в оверлее списка и отображается только в том случае, если список пуст.
2. Представление недоступности с действием
Это просто стандартное представление и, следовательно, оно поставляется с несколькими дополнительными встроенными модификаторами, такими как добавление действия к контенту.
Просто замените функцию getUnavailableContent()
в приведенном выше блоке кода на следующую функцию, и вы сможете получить дополнительную кнопку действия без каких-либо дополнительных усилий.
@ViewBuilder func getUnavailableContent() -> some View { ContentUnavailableView(label: { Text("Fetching Failed") .font(.largeTitle) .fontWeight(.bold) }, description: { Image(systemName: "text.page.slash") .font(.largeTitle) .foregroundStyle(.red) .symbolEffect(.wiggle.clockwise.wholeSymbol, options: .repeating) .padding(50) Text("No content here") .font(.title2) }, actions: { HStack(spacing: 24) { Button("Refresh", role: .cancel, action: {}) Button ("Go Back", role: .destructive, action: {}) .buttonStyle(.borderedProminent) } .fixedSize() .controlSize(.regular) }) }
3. Представление недоступности с пейджингом
Как я уже упоминал, это можно использовать для создания обучающего представления или представления с инструкциями, например, с пагинацией для онбординга или что-то в этом роде.
struct ContentViewPaging: View { var body: some View { getUnavailableContent() } @ViewBuilder func getUnavailableContent() -> some View { TabView { ContentUnavailableView { Image(systemName: "bonjour") .font(.largeTitle) .foregroundStyle(.blue) .symbolEffect(.rotate.clockwise.wholeSymbol, options: .repeating) .frame(width: 100, height: 100) .padding() Text("Welcome to our app") .font(.largeTitle) .fontWeight(.bold) } ContentUnavailableView { Image(systemName: "indianrupeesign.ring.dashed") .font(.largeTitle) .foregroundStyle(.pink) .symbolEffect(.rotate.clockwise.wholeSymbol, options: .repeating) .frame(width: 100, height: 100) .padding() Text("Continue with SignUp") .font(.largeTitle) .fontWeight(.bold) } ContentUnavailableView { Image(systemName: "apple.logo") .font(.largeTitle) .foregroundStyle(.green) .symbolEffect(.wiggle.clockwise.wholeSymbol, options: .repeating) .padding() Text("If already registered, SignIn") .font(.largeTitle) .fontWeight(.bold) } } .tabViewStyle(.page) .indexViewStyle(.page(backgroundDisplayMode: .always)) } }
В приведенном выше коде содержимое использует пагинацию.
Вы можете настроить любое представление, но использование ContentUnavailableView имеет особые преимущества. Это удобный способ информировать пользователей о недоступности содержимого, сохраняя при этом последовательный интерфейс. Такой подход повышает удобство работы пользователей, четко информируя их об отсутствии контента, и может побудить их предпринять альтернативные действия, например обновить страницу или перейти в другое место.
Это помогает:
- В ускорении разработки кода
- Вам не нужно беспокоиться о рендеринге в разных размерах
- Поставляется с действиями по умолчанию
Я надеюсь, что вы открыли для себя что-то новое или вновь обрели знания о знакомых концепциях!
-
Видео и подкасты для разработчиков4 недели назад
SwiftUI: алхимия приложений — превращаем идеи в реальность
-
Разработка4 недели назад
30 уроков от 30 лучших продуктовых лидеров
-
Новости4 недели назад
Видео и подкасты о мобильной разработке 2025.3
-
Магазины приложений1 неделя назад
Приложение Hot Tub появится на iOS в EC