Как с помощью SwiftUI уберечь обрезанное содержимое одного подпредставления от блокировки жестов в базовых подпредставлениях?

У меня есть главное представление, состоящее из zStack с фоновым изображением внизу, загруженным пользователем изображением над ним и двумя панелями инструментов вверху. Панели инструментов находятся вверху и внизу по вертикали. Я хочу, чтобы эти панели инструментов казались полупрозрачными с фоновыми изображениями, соответствующими фоновому изображению основного представления по размеру и положению. Если пользователь перетаскивает или масштабирует свое изображение так, чтобы оно перекрывалось панелями инструментов, оно должно быть закрыто ими. Для этого я построил эти панели инструментов как zStacks с одним и тем же фоновым изображением, выровненным по верхнему или нижнему краю соответственно, и вырезал содержимое, чтобы оно соответствовало высоте панелей инструментов.

Моя проблема в том, что обрезанное содержимое этих представлений панели инструментов блокирует жесты на нижележащем загруженном пользователем изображении. Чтобы помочь визуализировать проблему, я привел снимок экрана с иерархией представления отладки для основного представления (MockScoringView).

Вот код для основного представления:

GeometryReader { geometry in
            ZStack {

                Rectangle()
                    .foregroundColor(.blue)
                    .frame(width: geometry.size.width, height: geometry.size.height)
                    .offset(x: self.baseOffset.width + self.newOffset.width, y: self.baseOffset.height + self.newOffset.height)
                    .scaleEffect(self.scale)
                    .gesture(DragGesture()
                        .onChanged { value in
                                self.newOffset.width = value.translation.width / self.scale
                                self.newOffset.height = value.translation.height / self.scale
                        }
                        .onEnded { value in
                                self.baseOffset.width += self.newOffset.width
                                self.baseOffset.height += self.newOffset.height
                                self.newOffset = CGSize.zero
                        }
                    )

                VStack(spacing: 0) {
                    MockTopToolbarView()

                    Spacer()

                    MockBottomToolbarView()
                }
            }
        }

И код для верхней панели инструментов, которая очень похожа на ту, что внизу:

ZStack {
            Image("Background")
                .resizable()
                .scaledToFill()
                .frame(height: 56, alignment: .top)
                .clipped()

            Rectangle()
                .foregroundColor(.toolbarGray)
                .frame(height: 56)
        }

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

Иерархия представления отладки

1 ответ

Решение

Вы можете установить allowsHitTesting(false) на фоновых изображениях.

В качестве альтернативы, поскольку вы не хотите, чтобы изображение пользователя было видно за панелями инструментов, вы также можете просто добавить прямоугольник и панели инструментов в один VStack.

ZStack {
    Image("Background")
            .resizable()
            .scaledToFill()
    VStack {
        TopToolBar()
        Rectangle()
            .foregroundColor(.blue)
            ...
        BottomToolBar()
    }
}
Другие вопросы по тегам