Показ/скрытие элементов без нарушения работы других элементов представления

Вопрос или проблема

Я использовал прозрачность как способ показать или скрыть элементы вида, не нарушая макет представлений. В этом примере я хочу, чтобы метка всегда оставалась по центру относительно горизонтали, независимо от того, показываются ли изображения info1 или info2.

import SwiftUI

struct ContentView: View {
    @State var info1: Bool = false
    @State var info2: Bool = false
    @State var label: String = ""
    
    var body: some View {
        
        VStack {
            TextField("Введите метку", text: $label)
                .frame(width: 200)
            Toggle("Информация 1", isOn: $info1)
                .frame(width: 100)
            Toggle("Информация 2", isOn: $info2)
                .frame(width: 100)
                    
            HStack {
                Image(systemName: "info.circle.fill")
                    .opacity(info1 ? 1 : 0)
                Text(label)
                Image(systemName: "info.circle.fill")
                    .opacity(info2 ? 1 : 0)
            }
        }
    }
}

Я уверен, что есть лучший способ, но пока не нашел ничего, что подходит для работы в более сложных представлениях. Есть предложения?

Ответ или решение

Чтобы скрывать и показывать элементы в SwiftUI без нарушения расположения других элементов, можно использовать модификатор Hidden. Ваша текущая реализация с использованием свойства opacity действительно сохраняет размеры элементов, но может привести к тому, что визуальный порядок может быть не совсем удобным. Вместо этого, оптимально использовать условия для отображения или скрытия элементов, что позволит сохранить центрирование текста.

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

import SwiftUI

struct ContentView: View {
    @State var info1: Bool = false
    @State var info2: Bool = false
    @State var label: String = ""

    var body: some View {
        VStack {
            TextField("Введите метку", text: $label)
                .frame(width: 200)

            Toggle("Инфо 1", isOn: $info1)
                .frame(width: 100)

            Toggle("Инфо 2", isOn: $info2)
                .frame(width: 100)

            HStack {
                if info1 {
                    Image(systemName: "info.circle.fill")
                }

                Text(label)

                if info2 {
                    Image(systemName: "info.circle.fill")
                }
            }
            .frame(maxWidth: .infinity) // Центрирование HStack
        }
        .padding()
    }
}

Объяснение:

  1. Условное отображение элементов: Вместо использования opacity, мы используем условные операторы if, чтобы показать или скрыть значки Image. Когда info1 или info2 равны true, соответствующий значок отображается, и его размер занимает место в горизонтальном стеке HStack. Когда переменная равна false, элемент не занимает место.

  2. Центрирование текста: Используя frame(maxWidth: .infinity) для HStack, вы можете гарантировать, что содержимое будет отцентрировано внутри стека, независимо от видимости значков.

  3. Гибкость для более сложных интерфейсов: Этот подход позволяет легко добавлять другие элементы и поддерживать хорошее выравнивание, делая код более понятным и легко масштабируемым.

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

Оцените материал
Добавить комментарий

Капча загружается...