SwiftUI如何实现仅修改被选中的单个图片视图的透明度
解决方案
问题原因
你当前的代码中所有图片共用了同一个全局的opacity状态变量,只要这个变量发生变化,所有绑定了该变量的图片都会同步修改透明度,这就是点击任意图片全部变不透明的原因。
修改思路
我们需要单独记录被选中的图片索引,每个图片根据自身索引是否匹配选中索引来动态计算透明度即可:
- 将全局的透明度状态替换为可选类型的选中索引状态,默认值为
nil代表无选中图片 - 循环遍历的时候保留每个图片的索引值,不要用下划线忽略
- 每个图片的透明度通过「当前索引是否等于选中索引」动态判断
- 点击手势触发时将当前索引赋值给选中索引状态即可,如果需要支持点击已选中图片取消选中,也可以加额外判断逻辑
修改后的完整代码
struct TestView: View { // 替换为存储选中的图片索引,默认无选中 @State private var selectedIndex: Int? = nil let columns = [GridItem(.flexible(), spacing: 1), GridItem(.flexible(), spacing: 1), GridItem(.flexible(), spacing: 1)] // 默认透明度可以定义为常量 private let defaultOpacity: CGFloat = 0.5 var body: some View { ScrollView { LazyVGrid(columns: columns, spacing: 1) { // 保留每个元素的索引 ForEach(0..<90, id: \.self) { index in Image("placeholder") .resizable() .scaledToFill() .clipped() // 动态判断透明度:当前索引被选中则为1,否则用默认值 .opacity(selectedIndex == index ? 1 : defaultOpacity) .onTapGesture { // 支持点击已选中图片取消选中的写法,不需要的话直接写selectedIndex = index即可 if selectedIndex == index { selectedIndex = nil } else { selectedIndex = index } } } } } } }
拓展说明
如果需要支持同时选中多张图片,可以把selectedIndex的类型改成Set<Int>,点击的时候往集合里新增/移除对应索引,透明度判断改为集合是否包含当前索引即可。
内容的提问来源于stack exchange,提问作者Luis Ramirez
相关产品推荐
相关产品推荐

