Разработка
Малоизвестные представления 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 и проверяет дальше
- Рендерит первое представление, которое подходит для контейнера
- Если ни один из них не подходит, рендерится последний вид
Совет
- Начинайте проверку от самого верхнего вида к самому нижнему (см. пример кода)
xxxxxxxxxx
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. Основное представление недоступности:
xxxxxxxxxx
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()
в приведенном выше блоке кода на следующую функцию, и вы сможете получить дополнительную кнопку действия без каких-либо дополнительных усилий.
xxxxxxxxxx
@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. Представление недоступности с пейджингом
Как я уже упоминал, это можно использовать для создания обучающего представления или представления с инструкциями, например, с пагинацией для онбординга или что-то в этом роде.
xxxxxxxxxx
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 недели назад
Конец программирования в том виде, в котором мы его знаем
-
Видео и подкасты для разработчиков1 неделя назад
Как устроена мобильная архитектура. Интервью с тех. лидером юнита «Mobile Architecture» из AvitoTech
-
Магазины приложений3 недели назад
Магазин игр Aptoide запустился на iOS в Европе
-
Новости3 недели назад
Видео и подкасты о мобильной разработке 2025.8