我想显示图像列表。每个图像都有一个关联的文本,我想以“弹出窗口”的方式显示该文本(但如何实现并不重要 - 它不必作为弹出窗口“调用”),即在图像,但仅与文本实际大小一样大,图像应该仍然显示在文本周围的背景中。
我的图像位于
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)")
}
}
我就是这样做的:
在这种情况下,我赞成对弹出窗口进行条件视图。它具有更灵活的外观。
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
修饰符中,以按照指定的对齐方式堆叠在图像上。
我还添加了状态变化的动画,使其更加平滑。