programing

Swift UI가 HSack의 Spacer를 탭할 수 없습니다.

padding 2023. 8. 6. 09:53
반응형

Swift UI가 HSack의 Spacer를 탭할 수 없습니다.

목록 보기가 있고 목록의 각 행에는 일부 텍스트 보기와 다음과 같은 이미지가 포함되어 있습니다.

HStack{
    Text(group.name)
    Spacer()
    if (groupModel.required) { Text("Required").color(Color.gray) }
    Image("ic_collapse").renderingMode(.template).rotationEffect(Angle(degrees: 90)).foregroundColor(Color.gray)
}.tapAction { self.groupSelected(self.group) }

텍스트와 이미지 사이의 빈 섹션을 탭하는 경우를 제외하고는 이것이 잘 작동하는 것 같습니다(여기서Spacer()is) 탭 동작이 등록되지 않았습니다.탭 작업은 텍스트나 이미지를 누를 때만 수행됩니다.

이 문제를 해결할 수 있는 방법을 알고 있는 다른 사람이 있습니까?

최근에 알게 된 바와 같이 다음과 같은 것도 있습니다.

HStack {
  ...
}
.contentShape(Rectangle())
.onTapGesture { ... }

저한테는 잘 맞습니다.

그냥 사용하는 게 어때요?Button?

Button(action: { self.groupSelected(self.group) }) {
    HStack {
        Text(group.name)
        Spacer()
        if (groupModel.required) { Text("Required").color(Color.gray) }
        Image("ic_collapse").renderingMode(.template).rotationEffect(Angle(degrees: 90)).foregroundColor(Color.gray)
    }
}.foregroundColor(.primary)

버튼이 포인트 컬러를 적용하지 않으려면Text(group.name)설정해야 합니다.foregroundColor내가 예에서 했던 것처럼.

모든 뷰에서 마법처럼 작동합니다.

extension View {
    func onTapGestureForced(count: Int = 1, perform action: @escaping () -> Void) -> some View {
        self
            .contentShape(Rectangle())
            .onTapGesture(count:count, perform:action)
    }
}

접근성 문제에 대한 제 생각에 가장 좋은 접근법은 포장하는 것입니다.HStack의 내부에Button라벨, 그리고 문제를 해결하기 위해.Spacer탭할 수 없습니다. 추가할 수 있습니다..contentShape(Rectangle())에게HStack.

따라서 코드를 기준으로 다음과 같습니다.

Button {
    self.groupSelected(self.group)
} label: {
    HStack {
        Text(group.name)
        Spacer()
        if (groupModel.required) {
            Text("Required").color(Color.gray)
        }
        Image("ic_collapse")
            .renderingMode(.template)
            .rotationEffect(Angle(degrees: 90))
            .foregroundColor(Color.gray)
    }
    .contentShape(Rectangle())
}

Jim의 답변을 기반으로 한 단순 내선 번호

extension Spacer {
    /// https://stackoverflow.com/a/57416760/3393964
    public func onTapGesture(count: Int = 1, perform action: @escaping () -> Void) -> some View {
        ZStack {
            Color.black.opacity(0.001).onTapGesture(count: count, perform: action)
            self
        }
    }
}

이제 작동합니다.

Spacer().onTapGesture {
    // do something
}

저는 스페이서를 Z스택으로 포장하고 불투명도가 매우 낮은 단색을 추가함으로써 이 문제를 해결할 수 있었습니다.

ZStack {
    Color.black.opacity(0.001)
    Spacer()
}

배경색만 추가합니다(제외).clear색)을 위한HStack작동하다.

HStack {
        Text("1")
        Spacer()
        Text("1")
}.background(Color.white)
.onTapGesture(count: 1, perform: {

})

승인된 답변은 버튼 기능을 모방할 수 있지만 시각적으로는 만족스럽지 않습니다.대체하지 않음Button와 함께.onTapGesture또는UITapGestureRecognizer손가락 탭 이벤트를 받아들이는 영역만 필요한 경우는 제외합니다.이러한 솔루션은 진부한 것으로 간주되며 좋은 프로그래밍 관행이 아닙니다.

문제를 해결하려면 다음을 구현해야 합니다.BorderlessButtonStyle⚠️

일반 셀을 만듭니다. 예).SettingsNavigationCell.

설정내비게이션 셀

struct SettingsNavigationCell: View {
  
  var title: String
  var imageName: String
  let callback: (() -> Void)?

  var body: some View {
    
    Button(action: {
      callback?()
    }, label: {

      HStack {
        Image(systemName: imageName)
          .font(.headline)
          .frame(width: 20)
        
        Text(title)
          .font(.body)
          .padding(.leading, 10)
          .foregroundColor(.black)
        
        Spacer()
        
        Image(systemName: "chevron.right")
          .font(.headline)
          .foregroundColor(.gray)
      }
    })
    .buttonStyle(BorderlessButtonStyle()) // <<< This is what you need ⚠️
  }
}

설정 보기

struct SettingsView: View {
  
  var body: some View {
    
    NavigationView {
      List {
        Section(header: "Appearance".text) {
          
          SettingsNavigationCell(title: "Themes", imageName: "sparkles") {
            openThemesSettings()
          }
          
          SettingsNavigationCell(title: "Lorem Ipsum", imageName: "star.fill") {
            // Your function
          }
        }
      }
    }
  }
}

저는 이것에 대한 피드백을 제출했고, 당신도 그렇게 할 것을 제안합니다.

그동안 불투명했던Color와 마찬가지로 잘 작동해야 합니다.Spacer안타깝게도 배경색과 일치해야 하며, 단추 뒤에 표시할 내용이 없다고 가정합니다.

지금까지 언급된 모든 것의 정신에 따라:

struct NoButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .background(Color.black.opacity(0.0001))
    }
}
extension View {
    func wrapInButton(action: @escaping () -> Void) -> some View {
        Button(action: action, label: {
            self
        })
        .buttonStyle(NoButtonStyle())
    }
}

내가 만든 것은NoButtonStyle왜냐하면BorderlessButtonStyle여전히 다른 애니메이션을 제공하고 있었습니다..onTapGesture

예:

HStack {
    Text(title)
    Spacer()
    Text("Select Value")
    Image(systemName: "arrowtriangle.down.square.fill")
}
.wrapInButton {
    isShowingSelectionSheet = true
}

다른 옵션:

extension Spacer {
    func tappable() -> some View {
        Color.blue.opacity(0.0001)
    }
}

업데이트됨:

나는 그것을 알아차렸습니다.Color항상 같은 행동을 하는 것은 아닙니다.Spacer스택에 넣을 때, 저는 당신이 그러한 차이를 알지 못하는 한 그 Spacer 확장을 사용하지 않는 것을 제안합니다.(스페이서가 스택의 단일 방향으로 밀어넣습니다(스페이서가 스택에 있는 경우).VStack그것은 수직으로 밀립니다, 만약에.HStack그것은 수평으로 밀어내는 반면, a.Color뷰가 모든 방향으로 밀려나 있습니다.)

이 웹사이트는 저에게 같은 질문에 대답하는 데 도움이 되었습니다: https://www.hackingwithswift.com/quick-start/swiftui/how-to-control-the-tappable-area-of-a-view-using-contentshape

적용해 보십시오..ContentShape(Rectangle())에▁HStack.

빈 배경 수정자를 추가하는 것만으로도 작동합니다.

HStack {
  ...
}
.background()
.onTapGesture { ... }

세르히오 블랑쿠의 답변에 대한 업데이트.

  Button {
        self.groupSelected(self.group)
    }, label: {
        HStack {
            Text(group.name)
            Spacer()
            if (groupModel.required) {
                Text("Required").color(Color.gray)
            }
            Image("ic_collapse")
                .renderingMode(.template)
                .rotationEffect(Angle(degrees: 90))
                .foregroundColor(Color.gray)
        }
    }

전체 보기를 단추로 감싸면 됩니다.contentShape

언급URL : https://stackoverflow.com/questions/57191013/swiftui-cant-tap-in-spacer-of-hstack

반응형