有条件地在图像顶部显示文本

问题描述 投票:0回答:1

我想显示图像列表。每个图像都有一个关联的文本,我想以“弹出窗口”的方式显示该文本(但如何实现并不重要 - 它不必作为弹出窗口“调用”),即在图像,但仅与文本实际大小一样大,图像应该仍然显示在文本周围的背景中。

我的图像位于

HStack
VStack
中,具体取决于用户如何握住设备,并且我有一个按钮,我想用它来触发显示文本。我尝试了各种方法在不同的地方添加
.popover
修饰符,但没有成功显示任何内容,包括
Button
。但我还没有让它以任何方式工作。

我相当缺乏经验,所以答案可能是显而易见的!

GrannyStreamDataItem
数据结构目前使用命名图像,但这当然会在稍后改变。

当用户点击

i
按钮时如何触发并显示文本?

//Data structure

struct GrannyStreamDataItem: Identifiable {
    var id = UUID()
    var image: String
    var comment: String = ""
    var commentPosition: Alignment = .bottomLeading
}

let grannyStreamData: [GrannyStreamDataItem] = [
    GrannyStreamDataItem(image: "Pisa1", comment: "Leaning tower of Pisa. Gosh, it is crowded!", commentPosition: .topLeading),
    GrannyStreamDataItem(image: "Pisa2", comment: "This is what the tower looks like from the inside :-)", commentPosition: .topTrailing),
]


// View showing images 

struct ContentView: View {
    
    var body: some View {
        GeometryReader { geometry in
            
            if geometry.size.width > geometry.size.height {
                ScrollView(.horizontal) {
                    VStack {
                        Spacer()
                        HStack {
                            ImageViews(dataItemArray: grannyStreamData)
                        }
                        Spacer()
                    }

                }
            } else {
                ScrollView(.vertical) {
                    HStack {
                        Spacer()
                        VStack {
                            ImageViews(dataItemArray: grannyStreamData)
                        }
                        Spacer()
                    }
                }
            }
        }
    }
}


struct ImageViews: View {
    let dataItemArray: [GrannyStreamDataItem]
    
    var body: some View { 
        
        ForEach(dataItemArray) { dataItem in
            ZStack(alignment:dataItem.commentPosition) {
                Image(dataItem.image)
                    .resizable()
                    .aspectRatio(contentMode: .fit)
                Button {
                    showTextImage(description: dataItem.comment)
                } label: {
                    Image(systemName: "info.circle")
                        .padding(.all, 10)
                        .font(.largeTitle)
                        .foregroundColor(.black)
                }
                //.popover() here won't work... Why not?
                  
            }

        }
    }

    func showTextImage(description: String) {
        print("Image text: \(description)")
    }
    
}
swiftui overlay swiftui-zstack
1个回答
0
投票

我就是这样做的:
在这种情况下,我赞成对弹出窗口进行条件视图。它具有更灵活的外观。

struct ImageList: View {
    let dataItemArray: [GrannyStreamDataItem]
    
    var body: some View {
        ForEach(dataItemArray) { dataItem in
            ImageView(dataItem: dataItem)
        }
    }
}

struct ContentView: View {
    var body: some View {
        GeometryReader { geometry in
            if geometry.size.width > geometry.size.height {
                ScrollView(.horizontal) {
                    HStack {
                        ImageList(dataItemArray: grannyStreamData)
                    }
                    .padding(10)
                }
            } else {
                ScrollView(.vertical) {
                    VStack {
                        ImageList(dataItemArray: grannyStreamData)
                    }
                    .padding(10)
                }
            }
        }
    }
}

struct ImageView: View {
    let dataItem: GrannyStreamDataItem
    @State private var showComment: Bool = false
    
    var body: some View {
        Image(dataItem.image)
            .resizable()
            .aspectRatio(contentMode: .fit)
            .overlay(alignment: dataItem.commentPosition) {
                Group {
                    if showComment {
                        Text("Image text: \(dataItem.comment)")
                            .padding(10)
                            .background(.gray.opacity(0.6))
                            .cornerRadius(8)
                            .padding(10)
                    } else {
                        Image(systemName: "info.circle")
                            .padding(10)
                            .font(.largeTitle)
                            .foregroundColor(.black)
                    }
                }
                .onTapGesture {
                    withAnimation(.easeInOut(duration: 0.3)) {
                        showComment.toggle()
                    }
                }
            }
    }
}

我将

ImageViews
重命名为
ImageList
以避免以后出现任何名称混淆。
我从
HStack
中去掉了多余的
VStack
Spacer
contentView
,它们也比使用更麻烦。

我将

Image
Text
移至新视图
ImageView
。像这样,它们每个人都可以有自己的
@State
变量
showComment
。该变量可以通过
onTapGesture
切换,信息图像或评论文本将有条件地显示。请注意,
if
条件需要包含在
Group
视图中才能接受
onTapGesture
修饰符。该组包含在
overlay
修饰符中,以按照指定的对齐方式堆叠在图像上。

我还添加了状态变化的动画,使其更加平滑。

© www.soinside.com 2019 - 2024. All rights reserved.