Я хочу создать многоразовый компонент Swiftui, который отображает сетку карт. Макет должен быть гибким в зависимости от предоставленных данных. сторона.
Прямо сейчас я сделал это. Но должен быть лучший способ сделать это. struct SettingsCardView: View {
@ObservedObject var viewModel: SettingsCardItemViewModel
var body: some View {
BindableView(viewModel: viewModel) {
makeContent()
}
}
@ViewBuilder
private func makeContent() -> some View {
Button {
viewModel.onClick()
} label: {
VStack(alignment: .leading) {
TextView(viewModel.title)
TextView(viewModel.subtitle)
Spacer()
HStack {
Spacer()
makeIcon()
}
}
.modifier(SettingsCard())
}
}
@ViewBuilder
private func makeIcon() -> some View {
switch viewModel {
case let battery as BatterySettingsCardViewModel:
BatteryIcon(viewModel: battery.batteryIconViewModel)
case let greenLight as GreenStatusSettingsCardViewModel:
DefaultSettingsIcon(viewModel: greenLight.icon)
case let connectionNotification as ConnectionNotificationSettingsCardViewModel:
DefaultSettingsIcon(viewModel: connectionNotification.icon)
default:
EmptyView()
}
}
}
public class SettingsCardItemViewModel: BindableViewModel, Identifiable {
public var title: TextViewModel
public var subtitle: TextViewModel
public init(
title: String,
subtitle: String,
subtitleTextViewModel: TextViewModel? = nil
) {
self.title = .b1(title, color: .uiTextLightPrimary)
self.subtitle = subtitleTextViewModel ?? .b1(subtitle, color: .uiTextLightPrimaryInactive)
}
public func onClick() {
Debugger.fail(desc: "onClick not implemented")
}
}
public class BatterySettingsCardViewModel: SettingsCardItemViewModel {
public let batteryIconViewModel: BatteryIconViewModel
public init() {
self.batteryIconViewModel = BatteryIconViewModel()
super.init(title: "Battery", subtitle: "", subtitleTextViewModel: .h0("92%", color: .uiTextLightSecondary))
}
}
public class GreenStatusSettingsCardViewModel: SettingsCardItemViewModel {
public var icon: DefaultSettingsIconViewModel
public init() {
self.icon = DefaultSettingsIconViewModel(icon: .iconArrowLeft(.medium))
super.init(title: "Green status", subtitle: "Inactive")
}
public override func onClick() { }
}
public class ConnectionNotificationSettingsCardViewModel: SettingsCardItemViewModel {
public var icon: DefaultSettingsIconViewModel
public init() {
self.icon = DefaultSettingsIconViewModel(icon: .iconArrowLeft(.medium))
super.init(title: "Connection notifications", subtitle: "Inactive")
}
public override func onClick() { }
}
public class BatteryIconViewModel: BindableViewModel {
public override init() { }
}
public class BaseSettingsMenuSection: Identifiable, ObservableObject {
public var title: TextViewModel?
public var subtitle: TextViewModel?
@Published public var items: [SettingsCardItemViewModel]
public init(title: String? = nil, subtitle: String? = nil, items: [SettingsCardItemViewModel]) {
if let title {
self.title = .h2(title)
}
if let subtitle {
self.subtitle = .b1(subtitle, color: .uiTextLightSecondary)
}
self.items = items
}
}
public class OneColumn: BaseSettingsMenuSection { }
public class TwoColumn: BaseSettingsMenuSection { }
public class CameraSettingsCardViewModel: SettingsCardItemViewModel {
public var icon: DefaultSettingsIconViewModel
public init() {
self.icon = DefaultSettingsIconViewModel(icon: .iconSpeedCam(.medium))
super.init(title: "Cameras", subtitle: "Active")
}
}
public class RoadHazardSettingsCardViewModel: SettingsCardItemViewModel {
public var icon: DefaultSettingsIconViewModel
public init() {
self.icon = DefaultSettingsIconViewModel(icon: .iconRoadHazad(.medium))
super.init(title: "Road Hazard", subtitle: "InActive")
}
}
public class SpeedLimitSettingsCardViewModel: SettingsCardItemViewModel {
public var icon: DefaultSettingsIconViewModel
public init() {
self.icon = DefaultSettingsIconViewModel(icon: .iconSpeedCam(.medium))
super.init(title: "Speed Limit", subtitle: "Active")
}
}
public class NotificationSettingsCardViewModel: SettingsCardItemViewModel {
public var icon: DefaultSettingsIconViewModel
public init() {
self.icon = DefaultSettingsIconViewModel(icon: .iconNotificationOn(.medium))
super.init(title: "Notifications", subtitle: "Active")
}
}
struct SettingsMenuSectionView: View {
@ObservedObject var viewModel: BaseSettingsMenuSection
var body: some View {
VStack(alignment: .leading) {
VStack(alignment: .leading, spacing: 16) {
if let title = viewModel.title {
TextView(title)
}
if let subtitle = viewModel.subtitle {
TextView(subtitle)
}
}
makeItemList()
}
}
@ViewBuilder
private func makeItemList() -> some View {
switch viewModel {
case is OneColumn:
makeOneColumnItemList()
case is TwoColumn:
makeTwoColumnItemList()
default:
EmptyView()
}
}
@ViewBuilder
private func makeOneColumnItemList() -> some View {
VStack(spacing: Constants.Padding.padding8) {
ForEach(viewModel.items) { item in
SettingsCardView(viewModel: item)
}
}
}
@ViewBuilder
private func makeTwoColumnItemList() -> some View {
HStack(spacing: Constants.Padding.padding8) {
ForEach(viewModel.items) { item in
SettingsCardView(viewModel: item)
}
}
}
}
public class BaseSettingsMenuSection: Identifiable, ObservableObject {
public var title: TextViewModel?
public var subtitle: TextViewModel?
@Published public var items: [SettingsCardItemViewModel]
public init(title: String? = nil, subtitle: String? = nil, items: [SettingsCardItemViewModel]) {
if let title {
self.title = .h2(title)
}
if let subtitle {
self.subtitle = .b1(subtitle, color: .uiTextLightSecondary)
}
self.items = items
}
}
public class OneColumn: BaseSettingsMenuSection { }
public class TwoColumn: BaseSettingsMenuSection { }
Подробнее здесь: https://stackoverflow.com/questions/797 ... rid-layout
Как создать динамический компонент Swiftui с гибкой сеткой ⇐ IOS
Программируем под IOS
-
Anonymous
1759776244
Anonymous
Я хочу создать многоразовый компонент Swiftui, который отображает сетку карт. Макет должен быть гибким в зависимости от предоставленных данных. сторона.
Прямо сейчас я сделал это. Но должен быть лучший способ сделать это. struct SettingsCardView: View {
@ObservedObject var viewModel: SettingsCardItemViewModel
var body: some View {
BindableView(viewModel: viewModel) {
makeContent()
}
}
@ViewBuilder
private func makeContent() -> some View {
Button {
viewModel.onClick()
} label: {
VStack(alignment: .leading) {
TextView(viewModel.title)
TextView(viewModel.subtitle)
Spacer()
HStack {
Spacer()
makeIcon()
}
}
.modifier(SettingsCard())
}
}
@ViewBuilder
private func makeIcon() -> some View {
switch viewModel {
case let battery as BatterySettingsCardViewModel:
BatteryIcon(viewModel: battery.batteryIconViewModel)
case let greenLight as GreenStatusSettingsCardViewModel:
DefaultSettingsIcon(viewModel: greenLight.icon)
case let connectionNotification as ConnectionNotificationSettingsCardViewModel:
DefaultSettingsIcon(viewModel: connectionNotification.icon)
default:
EmptyView()
}
}
}
public class SettingsCardItemViewModel: BindableViewModel, Identifiable {
public var title: TextViewModel
public var subtitle: TextViewModel
public init(
title: String,
subtitle: String,
subtitleTextViewModel: TextViewModel? = nil
) {
self.title = .b1(title, color: .uiTextLightPrimary)
self.subtitle = subtitleTextViewModel ?? .b1(subtitle, color: .uiTextLightPrimaryInactive)
}
public func onClick() {
Debugger.fail(desc: "onClick not implemented")
}
}
public class BatterySettingsCardViewModel: SettingsCardItemViewModel {
public let batteryIconViewModel: BatteryIconViewModel
public init() {
self.batteryIconViewModel = BatteryIconViewModel()
super.init(title: "Battery", subtitle: "", subtitleTextViewModel: .h0("92%", color: .uiTextLightSecondary))
}
}
public class GreenStatusSettingsCardViewModel: SettingsCardItemViewModel {
public var icon: DefaultSettingsIconViewModel
public init() {
self.icon = DefaultSettingsIconViewModel(icon: .iconArrowLeft(.medium))
super.init(title: "Green status", subtitle: "Inactive")
}
public override func onClick() { }
}
public class ConnectionNotificationSettingsCardViewModel: SettingsCardItemViewModel {
public var icon: DefaultSettingsIconViewModel
public init() {
self.icon = DefaultSettingsIconViewModel(icon: .iconArrowLeft(.medium))
super.init(title: "Connection notifications", subtitle: "Inactive")
}
public override func onClick() { }
}
public class BatteryIconViewModel: BindableViewModel {
public override init() { }
}
public class BaseSettingsMenuSection: Identifiable, ObservableObject {
public var title: TextViewModel?
public var subtitle: TextViewModel?
@Published public var items: [SettingsCardItemViewModel]
public init(title: String? = nil, subtitle: String? = nil, items: [SettingsCardItemViewModel]) {
if let title {
self.title = .h2(title)
}
if let subtitle {
self.subtitle = .b1(subtitle, color: .uiTextLightSecondary)
}
self.items = items
}
}
public class OneColumn: BaseSettingsMenuSection { }
public class TwoColumn: BaseSettingsMenuSection { }
public class CameraSettingsCardViewModel: SettingsCardItemViewModel {
public var icon: DefaultSettingsIconViewModel
public init() {
self.icon = DefaultSettingsIconViewModel(icon: .iconSpeedCam(.medium))
super.init(title: "Cameras", subtitle: "Active")
}
}
public class RoadHazardSettingsCardViewModel: SettingsCardItemViewModel {
public var icon: DefaultSettingsIconViewModel
public init() {
self.icon = DefaultSettingsIconViewModel(icon: .iconRoadHazad(.medium))
super.init(title: "Road Hazard", subtitle: "InActive")
}
}
public class SpeedLimitSettingsCardViewModel: SettingsCardItemViewModel {
public var icon: DefaultSettingsIconViewModel
public init() {
self.icon = DefaultSettingsIconViewModel(icon: .iconSpeedCam(.medium))
super.init(title: "Speed Limit", subtitle: "Active")
}
}
public class NotificationSettingsCardViewModel: SettingsCardItemViewModel {
public var icon: DefaultSettingsIconViewModel
public init() {
self.icon = DefaultSettingsIconViewModel(icon: .iconNotificationOn(.medium))
super.init(title: "Notifications", subtitle: "Active")
}
}
struct SettingsMenuSectionView: View {
@ObservedObject var viewModel: BaseSettingsMenuSection
var body: some View {
VStack(alignment: .leading) {
VStack(alignment: .leading, spacing: 16) {
if let title = viewModel.title {
TextView(title)
}
if let subtitle = viewModel.subtitle {
TextView(subtitle)
}
}
makeItemList()
}
}
@ViewBuilder
private func makeItemList() -> some View {
switch viewModel {
case is OneColumn:
makeOneColumnItemList()
case is TwoColumn:
makeTwoColumnItemList()
default:
EmptyView()
}
}
@ViewBuilder
private func makeOneColumnItemList() -> some View {
VStack(spacing: Constants.Padding.padding8) {
ForEach(viewModel.items) { item in
SettingsCardView(viewModel: item)
}
}
}
@ViewBuilder
private func makeTwoColumnItemList() -> some View {
HStack(spacing: Constants.Padding.padding8) {
ForEach(viewModel.items) { item in
SettingsCardView(viewModel: item)
}
}
}
}
public class BaseSettingsMenuSection: Identifiable, ObservableObject {
public var title: TextViewModel?
public var subtitle: TextViewModel?
@Published public var items: [SettingsCardItemViewModel]
public init(title: String? = nil, subtitle: String? = nil, items: [SettingsCardItemViewModel]) {
if let title {
self.title = .h2(title)
}
if let subtitle {
self.subtitle = .b1(subtitle, color: .uiTextLightSecondary)
}
self.items = items
}
}
public class OneColumn: BaseSettingsMenuSection { }
public class TwoColumn: BaseSettingsMenuSection { }
Подробнее здесь: [url]https://stackoverflow.com/questions/79783978/how-to-create-a-dynamic-swiftui-component-with-flexible-grid-layout[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия