SwiftUI에서 YouTube와 유사한 필터링 구현

16844 단어 uxprogrammingiosswift
SwiftUI에는 .pickerStyle(.segmented) 또는 .pickerStyle(.wheel) 와 같은 몇 가지 기본 디자인과 함께 제공되는 Pickers 을 사용하는 자체 라디오 버튼 구현이 있습니다. 선택기는 필터링 기능을 구현하는 데 유용할 수 있지만 사용자 정의 디자인 및 동작(예: YouTube와 같은 디자인 및 동작)을 원하는 경우에는 어떻게 해야 할까요?

YouTube와 유사한 필터링은 버튼이 배치된 가로 스크롤 보기를 사용하며 각각 고유한 상태를 가지며 선택한 버튼은 서로 다른 색상을 가집니다.



요구 사항



사용자 지정 YouTube와 같은 필터링을 구현하기 전에 사용자 지정 보기가 충족해야 하는 몇 가지 요구 사항을 정의해 보겠습니다.
  • 뷰가 YouTube와 같은 필터링을 모방해야 함
  • 보기에서 열거형을 사용해야 함
  • 보기가 일반적이어야 함
  • 보기가 상태 비저장이어야 함

  • 상태 처리



    상태를 처리하기 위해 사용자 정의 필터 보기는 Swift Enumerations 을 사용합니다. Swift의 열거형은 매우 강력하며 각 열거형 사례가 선택되면 보기에 표시되는 데이터를 필터링하는 이상적인 방법입니다. 사용자 정의 필터 보기는 열거형이 String , CaseIterableIdentifiable 와 같은 몇 가지 프로토콜을 준수하도록 요구합니다.

    응용 프로그램이 구매할 수 있는 자동차 목록을 표시하고 유형을 기준으로 필터링하려고 한다고 가정해 보겠습니다. 이러한 경우 목록에 있는 각 자동차의 유형을 정의하는 열거형CarType을 생성합니다.

    차종:

    enum CarType: String, CaseIterable, Identifiable {
        var id: String { self.rawValue }
        case all, family, city, luxury, supercar
    }
    


    각 프로토콜이 필요한 이유에 대한 설명:
  • String - SwiftUI
  • 에서 Text 보기에 필요한 각 열거형 케이스의 원시 값이 문자열로 표시되기를 원합니다.
  • CaseIterable - 이 프로토콜을 준수하면 SwiftUI의 ForEach 루프에 필요한 유형의 allCases 속성을 사용하여 모든 유형의 사례 모음에 액세스할 수 있습니다
  • .
  • Identifiable - SwiftUI
  • ForEach 루프에 필요한 각 열거형 상태에 고유 ID를 제공합니다.

    보기 구현



    이전에 정의된 요구 사항을 충족하려면 사용자 정의 보기가 이전 단계에서 정의된 열거 모델과 일치하는 제네릭을 지원해야 합니다.

    FilterRowView:

    import SwiftUI
    
    struct FilterRowView<T>: View
        where T: RawRepresentable, T: CaseIterable, T: Identifiable, T.AllCases == [T], T.RawValue == String {
    
        @State private var selectedFilter: T = T.allCases[0]
    
        var body: some View {
            ScrollView(.horizontal, showsIndicators: false) {
                LazyHStack(spacing: 15) {
                    ForEach(T.allCases) { filter in
                        Button(action: {
                            withAnimation(Animation.spring().speed(1.5)) {
                                selectedFilter = filter
                            }
                        }) {
                            Text(filter.rawValue.capitalized)
                                .font(.subheadline)
                        }
                        .buttonStyle(FilterButtonStyle(isSelected: selectedFilter == filter))
                    }
                }
            }
            .frame(height: 40)
        }
    }
    


    보시다시피 뷰는 사용자 지정ButtonStyle을 사용하여 YouTube와 같은 디자인을 모방합니다.

    FilterButtonStyle:

    struct FilterButtonStyle: ButtonStyle {
    
        let isSelected: Bool
    
        func makeBody(configuration: Self.Configuration) -> some View {
        configuration.label
          .foregroundColor(
            isSelected ? .white : .black
          )
          .padding()
          .frame(maxWidth: .infinity, maxHeight: 30)
          .background(
            isSelected ? .black : .white
          )
          .cornerRadius(24)
          .overlay(
            RoundedRectangle(cornerRadius: 24)
                .stroke(isSelected ? .white : .black, lineWidth: 0.3)
          )
      }
    }
    


    FilterRowView는 이제 다음과 같아야 합니다.



    각각 고유한 상태를 가진 버튼이 있는 가로로 스크롤 가능한 보기이며 선택한 버튼은 서로 다른 색상을 가집니다.

    상태 게양



    눈치채셨겠지만 FilterRowView는 실제로 아무 작업도 수행하지 않으므로 데이터 필터링 기능을 추가해야 하지만 요구 사항 섹션에 설명된 대로 뷰는 상태 비저장이어야 합니다.

    그렇게하는 방법? 상태 호이스팅 패턴을 사용합니다. 저게 뭐에요? 그것을 설명합시다.

    상태 호이스팅은 React applications 개발을 위한 잘 알려진 패턴이며, 최근 Google에서는 응용 프로그램Jetpack Compose을 개발할 때 사용하도록 권장하고 있습니다.

    State hoisting is a pattern of moving state to a caller to make view stateless.



    실제로 이는 Swift 용어로 closures 을 사용하는 것을 의미하는 고차 함수를 사용하는 것을 의미합니다.
    FilterRowView에서 상태 호이스팅 패턴을 사용하려면 두 줄의 코드만 더 있으면 됩니다. 클로저를 허용하는 새 매개변수에 대한 한 줄과 클로저에 일반 유형을 제공하는 한 줄.

    업데이트된 FilterRowView:

    import SwiftUI
    
    struct FilterRowView<T>: View
        where T: RawRepresentable, T: CaseIterable, T: Identifiable, T.AllCases == [T], T.RawValue == String {
    
        let block: (T) -> Void
        @State private var selectedFilter: T = T.allCases[0]
    
        var body: some View {
            ScrollView(.horizontal, showsIndicators: false) {
                LazyHStack(spacing: 15) {
                    ForEach(T.allCases) { filter in
                        Button(action: {
                            withAnimation(Animation.spring().speed(1.5)) {
                                selectedFilter = filter
                            }
                            block(filter)
                        }) {
                            Text(filter.rawValue.capitalized)
                                .font(.subheadline)
                        }
                        .buttonStyle(FilterButtonStyle(isSelected: selectedFilter == filter))
                    }
                }
            }
            .frame(height: 40)
        }
    }
    


    이것으로 FilterRowView는 완전히 무국적이며 유용한 작업을 수행하기 위해 호출자에 의존합니다.

    애플리케이션에서 이를 사용하려면 다음과 같이 FilterRowView 보기를 호출합니다.

    FilterRowView<CarType>(block: { type in
        viewModel.filterCars(by: type)
    })
    


    결론



    읽어 주셔서 감사합니다. 이 기사가 도움이 되었기를 바랍니다. 결론적으로 이 기사에서는 열거형, 제네릭 및 클로저를 사용하여 SwiftUI에서 사용자 지정 YouTube와 유사한 필터링을 구현하는 방법을 살펴보았습니다.


    내 콘텐츠가 마음에 들고 유용하다고 생각되면 나를 팔로우하는 것을 고려하십시오. 특별히 관대하다고 느끼신다면 buying me a coffee을 고려하십시오.

    에서 나와 연결하세요.

    좋은 웹페이지 즐겨찾기