SwiftUI ONTAPPORATION on Color.clear背景与Color.blue的行为不同
我正在SwiftUI ONTAPPORATION on Color.clear背景与Color.blue的行为不同,swiftui,Swiftui,我正在SegmentedPickerStyle()中制作一个自定义选择器。我希望有相同的行为,但当我点击其中一个可能选择的内容和边框之间的区域时,ontapsignate不起作用。当我添加一个蓝色背景时,它确实可以工作,但如果背景清晰,它就不能工作 在蓝色背景下工作 背景不清楚 非工作代码: import SwiftUI struct PickerElementView<Content>: View where Content : View { @Binding var
SegmentedPickerStyle()
中制作一个自定义选择器。我希望有相同的行为,但当我点击其中一个可能选择的内容和边框之间的区域时,ontapsignate
不起作用。当我添加一个蓝色背景时,它确实可以工作,但如果背景清晰,它就不能工作
在蓝色背景下工作
背景不清楚
非工作代码:
import SwiftUI
struct PickerElementView<Content>: View where Content : View {
@Binding var selectedElement: Int
let content: () -> Content
@inlinable init(_ selectedElement: Binding<Int>, @ViewBuilder content: @escaping () -> Content) {
self._selectedElement = selectedElement
self.content = content
}
var body: some View {
GeometryReader { proxy in
self.content()
.fixedSize(horizontal: true, vertical: true)
.frame(minWidth: proxy.size.width, minHeight: proxy.size.height)
// ##################################################################
// CHANGE COLOR HERE TO BLUE TO MAKE IT WORK
// ##################################################################
.background(Color.clear)
// ##################################################################
.border(Color.yellow, width: 5)
}
}
}
struct PickerView: View {
@Environment (\.colorScheme) var colorScheme: ColorScheme
var elements: [(id: Int, view: AnyView)]
@Binding var selectedElement: Int
@State var internalSelectedElement: Int = 0
private var width: CGFloat = 220
private var height: CGFloat = 100
private var cornerRadius: CGFloat = 20
private var factor: CGFloat = 0.95
private var color = Color(UIColor.systemGray)
private var selectedColor = Color(UIColor.systemGray2)
init(_ selectedElement: Binding<Int>) {
self._selectedElement = selectedElement
self.elements = [
(id: 0, view: AnyView(PickerElementView(selectedElement) {
Text("9").font(.system(.title))
})),
(id: 1, view: AnyView(PickerElementView(selectedElement) {
Text("5").font(.system(.title))
})),
]
self.internalSelectedElement = selectedElement.wrappedValue
}
func calcXPosition() -> CGFloat {
var pos = CGFloat(-self.width * self.factor / 4)
pos += CGFloat(self.internalSelectedElement) * self.width * self.factor / 2
return pos
}
var body: some View {
ZStack {
Rectangle()
.foregroundColor(self.selectedColor)
.cornerRadius(self.cornerRadius * self.factor)
.frame(width: self.width * self.factor / CGFloat(self.elements.count), height: self.height - self.width * (1 - self.factor))
.offset(x: calcXPosition())
.animation(.easeInOut(duration: 0.2))
HStack {
ForEach(self.elements, id: \.id) { item in
item.view
.gesture(TapGesture().onEnded { _ in
print(item.id)
self.selectedElement = item.id
withAnimation {
self.internalSelectedElement = item.id
}
})
}
}
}
.frame(width: self.width, height: self.height)
.background(self.color)
.cornerRadius(self.cornerRadius)
.padding()
}
}
struct PickerView_Previews: PreviewProvider {
static var previews: some View {
PickerView(.constant(1))
}
}
导入快捷界面
结构PickerElementView:视图,其中内容:视图{
@绑定变量selectedElement:Int
让内容:()->内容
@Inlineable init(selectedElement:Binding,@ViewBuilder内容:@escaping()->content){
self.\u selectedElement=selectedElement
self.content=内容
}
var body:一些观点{
GeometryReader{中的代理
self.content()
.fixedSize(水平:真,垂直:真)
.frame(最小宽度:proxy.size.width,最小高度:proxy.size.height)
// ##################################################################
//将此处的颜色更改为蓝色以使其正常工作
// ##################################################################
.背景(颜色.清晰)
// ##################################################################
.边框(颜色.黄色,宽度:5)
}
}
}
结构PickerView:视图{
@环境(\.colorScheme)变量colorScheme:colorScheme
var元素:[(id:Int,view:AnyView)]
@绑定变量selectedElement:Int
@状态变量internalSelectedElement:Int=0
专用变量宽度:CGFloat=220
专用变量高度:CGFloat=100
专用var转弯半径:CGFloat=20
私人var系数:CGFloat=0.95
private var color=color(UIColor.systemGray)
私有变量selectedColor=Color(UIColor.systemGray2)
init(uselectedelement:Binding){
self.\u selectedElement=selectedElement
self.elements=[
(id:0,视图:任意视图(PickerElementView(selectedElement)){
文本(“9”).font(.system(.title))
})),
(id:1,视图:任意视图(PickerElementView(selectedElement)){
文本(“5”).font(.system(.title))
})),
]
self.internalSelectedElement=selectedElement.wrappedValue
}
func calcXPosition()->CGFloat{
var pos=CGFloat(-自宽*自系数/4)
pos+=CGFloat(self.internalSelectedElement)*self.width*self.factor/2
返回位置
}
var body:一些观点{
ZStack{
矩形()
.foregroundColor(自选颜色)
.转角半径(自转角半径*自转角系数)
.frame(宽度:self.width*self.factor/CGFloat(self.elements.count),高度:self.height-self.width*(1-self.factor))
.offset(x:calcXPosition())
.animation(.easeInOut(持续时间:0.2))
HStack{
ForEach(self.elements,id:\.id){item in
item.view
.手势(点击手势().onEnded{uu}in
打印(项目id)
self.selectedElement=item.id
动画片{
self.internalSelectedElement=item.id
}
})
}
}
}
.框架(宽度:自宽,高度:自高)
.背景(自身颜色)
.转角半径(自转角半径)
.padding()
}
}
结构PickerView\u预览:PreviewProvider{
静态var预览:一些视图{
PickerView(.常量(1))
}
}
更改我标记的颜色
有人知道为什么它们的行为会不同吗?我如何解决这个问题?似乎是一个设计决策,任何不透明度为0的颜色都是不可见的
Color.clear.onTapGesture { print("tapped") } // will not print
Color.blue.opacity(0).onTapGesture { print("tapped") } // will not print
Color.blue.onTapGesture { print("tapped") } // will print
Color.blue.opacity(0.0001).onTapGesture { print("tapped") } // will print
您可以使用第四个选项来解决这个问题,因为它在视觉上与第一个选项不可区分。一行答案不是设置背景色,请为命中测试设置contentShape
var body: some View {
GeometryReader { proxy in
self.content()
.fixedSize(horizontal: true, vertical: true)
.frame(minWidth: proxy.size.width, minHeight: proxy.size.height)
// ##################################################################
// CHANGE COLOR HERE TO BLUE TO MAKE IT WORK
// ##################################################################
.contentShape(Rectangle())
// ##################################################################
.border(Color.yellow, width: 5)
}
}
在SwiftUI中,透明视图默认情况下不可点击,因为其内容形状为零
您可以使用.contentShape
修改器更改此行为:
Color.clear
.框架(宽度:300,高度:300)
.contentShape(矩形())
.ontaps{print(“tapped”)}
我遇到了一个类似的问题,那就是如何在圆形直角上敲击
我的简单解决方案是将不透明度设置为一个非常低的值,这样就行了
RoundedRectangle(cornerRadius: 12)
.fill(Color.black)
.opacity(0.0001)
.frame(width: 32, height: 32)
.onTapGesture {
...
}
谢谢,我将暂时使用它,但这似乎更像是一种解决方法。是的,可能值得提交反馈,即能够在透明视图上注册一个手势会很好。如果默认设置是禁用透明视图的命中测试,这没关系,但是添加一个明确的手势应该会覆盖它,我同意!我将提交反馈,并尝试提出一个更优雅的解决方案。也许其他人会回答这个问题,或者给我一个正确的提示。。frame(maxWidth:.infinity,maxHeight:.infinity)
非常有用nicer@pleshis没有contentShape,无论框架如何,都无法工作。它不会在非渲染区域上注册接触。这是一个经常让人非常困惑的优化问题。最近在一个游戏库中出现了这个问题,尽管你经常想在其中使用触发器。