ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • BorderlessButtonStyle의 활용
    SwiftUI 2023. 10. 19. 08:35

    안녕하세요. 그린입니다 🍏

    이번 포스팅에서는 SwiftUI의 버튼을 다룰때 스타일을 지정할 수 있는데요.

    그 중 BorderlessButtonStyle을 알아보고 그 스타일을 어떻게 실전에서 적용하는 경우가 있을지 코드로 구현해보겠습니다 🙋🏻

     

    우선 BorderlessButtonStyle에 대해 공식문서를 통해 알아볼까요?


    BorderlessButtonStyle

    정말 해당 스타일의 의미는 보더 즉, 테두리를 적용하지 않은 버튼 스타일입니다.

    기본적으로 Button의 buttonStyle 모디파이어를 통해 버튼 스타일을 제공하고자 할때, static 변수로 .borderless가 있기에 쉽게 사용할 수 있습니다.

     

    이게 끝이에요 설명은 사실!

     

    그럼 디자인적인것 외에 현업에서 이 BorderlessButtonStyle을 어떤 경우 활용할 수 있는지 그게 오늘의 핵심입니다 😀

     

    아 뭔가 간단하지만 왠지 난관이 있을것 같긴한데... 가볼까요!?

     

     


    BorderlessButtonStyle 활용하기

    우선, 해당 버튼 스타일을 적용하지 않은 기본적인 코드를 먼저 봐볼께요!

     

    struct ContentView: View {
      @State var title: String = ""
      var colors: [Color] = [.orange, .red, .blue, .black, .brown]
      
      var body: some View {
        VStack {
          Text(title)
            .font(.title)
            .bold()
          
          List {
            ForEach(colors, id: \.self) { color in
              CellView(title: $title, color: color)
                .onTapGesture {
                  title = "\(color.description) Cell Tapped"
                }
            }
          }
          .listStyle(.plain)
        }
      }
    }
    
    private struct CellView: View {
      @Binding var title: String
      var color: Color
      
      var body: some View {
        VStack {
          RoundedRectangle(cornerRadius: 10)
            .fill(color)
            .frame(width: 100, height: 100)
          
          Button(
            action: {
              title = "\(color.description) Button Clicked"
            },
            label: {
              Text("Click Button")
            }
          )
    
          Spacer()
        }
      }
    }

     

    간단히 설명해보자면 List를 활용하여 CellView를 만들어서 목록으로 보여주는 뷰입니다.

    즉, 목록의 셀뷰에는 해당 지정된 컬러 둥그런 사각형과 버튼이 들어가게 됩니다.

     

    중요한 부분은 탭 이벤트가 발생해야하는 부분이 두가지입니다.

     

    하나는, 셀 뷰 자체를 클릭했을때 상단 타이틀이 Cell Tapped 문구로 변해야하구요!

    둘째로, 각 셀 뷰에 있는 Click Button 문구를 가진 버튼을 클릭하면 Button Clicked 문구로 타이틀이 변해야되죠.

     

    그럼 한번 이거 동작시켜볼까요~?

     

     

    보시면 색상이 입혀진 사각형을 누르면 Cell Tapped 문구가 노출되지만 Click Button을 누르면 해당 버튼이 동작하지 않고 Cell Tapped 즉, 상위 onTapGesture가 동작하는것을 볼 수 있습니다.

     

    또한, 심지어 빈 영역을 클릭하면 Click Button이 동작하는것을 볼 수가 있구요.

     

    자 이렇게 의도치않게 동작하는 이유가 있습니다.

     

    바로, SwiftUI의 이벤트 처리 우선순위와 관련이 있습니다 🙋🏻

    우선 우리는 상단뷰에 onTapGesture를 입혔고 하단 Button에서도 액션으로 하위 인터랙션이 발생해요.

    그럼 실제로 하단 뷰에 있는 Button을 누르게 되면 View 계층 구조에서 이벤트가 상위 뷰로 전파되는 "이벤트 버블링(Event Bubbling)"이라는 개념이 적용됩니다.

     

    즉, 하위 뷰에서 발생한 이벤트가 상위 뷰로 전달되면서 상위 뷰의 이벤트 핸들러가 우선적으로 동작하게 되는것이죠!

     

    실제, 하위 뷰 CellView에 있는 버튼은 탭(Gesture) 이벤트를 처리하기 위한것이 아닌 클릭 액션을 처리하기 위한것입니다.

    그렇기에 이벤트 버블링으로 하위 뷰의 클릭 액션이 무시되는것이죠.

     

    이것을 그럼 두가지 방법으로 해결해볼까 합니다 🙋🏻


    1️⃣ onTapGesture 이용하기

    Button의 형태를 우선 코드처럼 Text로 변경하고 onTapGesture를 사용하면 됩니다.

     

    private struct CellView: View {
      @Binding var title: String
      var color: Color
      
      var body: some View {
        VStack {
          RoundedRectangle(cornerRadius: 10)
            .fill(color)
            .frame(width: 100, height: 100)
          
          Text("Click Button")
            .onTapGesture {
              title = "Button Clicked"
            }
    
          Spacer()
        }
      }
    }

     

    이렇게 된다면 이벤트 버블링이 일어나지 않게됨으로 해당 버튼과 셀이 눌렸을때 각기 동작을 해줄 수 있죠.

    사실 셀 안에 이 Click Button이 존재하고 있는것이지만 우리는 상위로 이벤트를 전달하는것보다 원하는것은 하위에 있는 버튼의 이벤트가 우선순위로 적용하길 원하니까요! 😊

     


    2️⃣ BorderlessButtonStyle 적용하기

    두번째로는 우리가 오늘 간단히 살펴봤던 BorderlessButtonStyle를 이용하여 버튼을 구성해주는 방식입니다.

     

    우선 코드로 볼까요?

     

    private struct CellView: View {
      @Binding var title: String
      var color: Color
      
      var body: some View {
        VStack {
          RoundedRectangle(cornerRadius: 10)
            .fill(color)
            .frame(width: 100, height: 100)
          
          Button(
            action: {
              title = "Button Clicked"
            },
            label: {
              Text("Click Button")
            }
          )
          .buttonStyle(.borderless)
    
          Spacer()
        }
      }
    }

     

    아주 간단하게 하위 뷰에서 해당 버튼에 버튼 스타일을 borderless 즉, BorderlessButtonStyle로 static 변수로 만들어진 값을 넣어주면 됩니다.

     

    이렇게 되면 경계가 없는 버튼이 만들어지게 되죠?

    그런데 여기서 경계가 없다는것은 버튼의 탭 대상 영역이 최대한 크게 설정되어서 부모 뷰의 onTapGesture가 트리거 되는 것을 방지할 수 있습니다.

     

    그럼 한번 동작을 볼까요?

     

    짜잔---!!

    아주 의도대로 잘 동작하지 않나요?ㅎㅎ

     

    이렇게 두가지 방법으로 이벤트 트리거의 우선순위를 잡아봤습니다.

    특히 오늘 목표였던 BorderlessButtonStyle를 어떻게 실제로 활용할 수 있을지 디자인적인 부분 빼고 기능적으로 알아볼 수 있었습니다 🤩

     


    마무리

    새로운 개념 등장!

    Event Bubbling 🫧🫧🫧

    요거 다음 주제로 한번 가져와보겠습니다ㅎㅎ

     


    레퍼런스

    https://developer.apple.com/documentation/swiftui/borderlessbuttonstyle

     

    BorderlessButtonStyle | Apple Developer Documentation

    A button style that doesn’t apply a border.

    developer.apple.com

Designed by Tistory.