고급 장소 세부정보 구성요소
장소 세부정보 고급 버전 구성요소는 장소 세부정보 기본 버전과 동일한 기능을 제공합니다. 또한 장소 이름을 표시할지 여부를 선택하고, 구성요소의 작업 버튼을 구성하고, 표시되는 리뷰 및 미디어에 검색 및 필터링 옵션을 적용할 수 있습니다.
고급 장소 세부정보 구성
AdvancedPlaceDetailsView 또는 AdvancedPlaceDetailsCompactView를 사용하여 고급 기능에 액세스합니다.
콘텐츠 표시 옵션
AdvancedPlaceDetailsContent의 enum을 사용하여 표시할 콘텐츠를 지정할 수 있습니다. 장소 세부정보 기본사항과 동일한 콘텐츠를 모두 구성할 수 있으며 장소 이름을 표시할지 여부도 선택할 수 있습니다.
작업 버튼 구성
AdvancedPlaceDetailsView 또는 AdvancedPlaceDetailsCompactView의 .cornerActions 및 .mainActions 메서드를 사용하여 작업 버튼을 삭제하거나 맞춤설정합니다.
시각적 저작자 표시 요구사항
중요: 맞춤 작업 버튼이 Google 이외의 서드 파티와 사용자 정보를 공유하는 경우 최종 사용자에게 이를 명확히 알려야 합니다. 시각적 저작자 표시 요구사항을 참고하세요.
오른쪽의 예는 사용자 정보가 'Altostrat'로 전송된다는 것을 명확하게 보여주는 맞춤 이미지를 보여줍니다.
검색 및 필터링 옵션 적용
AdvancedPlaceDetailsView 또는 AdvancedPlaceDetailsCompactView의 .searchMediaOptions 및 .searchReviewOptions 메서드를 사용하여 미디어 또는 리뷰의 검색 및 필터링을 사용 설정합니다.
맞춤 콘텐츠 슬롯 만들기
맞춤 콘텐츠 슬롯을 사용하면 사전 정의된 레이아웃 영역에 자체 콘텐츠 (예: AI 생성 요약, 일정 타임스탬프, 맞춤 배지)를 직접 추가할 수 있습니다.
맞춤 콘텐츠를 추가하려면 AdvancedPlaceDetailsCompactView의 .placeDetailsCompactContentSlot 메서드를 사용합니다. 사용 가능한 위치는 .basicSectionTop 및 .basicSectionBottom입니다.
콘텐츠 슬롯의 저작자 표시 요구사항 및 콘텐츠 추천
맞춤 콘텐츠 슬롯이 마운트되면 Google에서 제공하는 콘텐츠와 서드 파티에서 제공하는 콘텐츠를 명확히 구분하도록 공개 문구가 자동으로 업데이트됩니다.
권장사항
Google 장소 세부정보와 맞춤 콘텐츠 간에 명확한 시각적 계층 구조를 유지하여 정보의 출처가 모호해지지 않도록 합니다.
권장사항
사용자의 즉각적인 목표에 맞춘 현지화된 고가치 통계를 고려하세요. 실시간 예약 기간이나 현재 예약 가능 여부와 같은 맞춤형 콘텐츠는 사용자가 더 빠르고 정보에 입각한 결정을 내리는 데 도움이 됩니다.
금지사항
Google에서 제공하는 콘텐츠를 숨긴 경우에도 평점, 리뷰, 영업시간과 같은 기존 Google 장소 세부정보를 중복으로 표시하지 마세요. 이렇게 하면 사용자가 콘텐츠의 출처가 Google인지 서드 파티인지 혼동할 수 있습니다.
금지사항
공식적인 Google 보증으로 오인될 수 있는 출처가 없는 주장이나 배지 (예: '최고의 추천')를 표시하지 마세요. 맞춤 콘텐츠는 출처를 명시적으로 표시해야 합니다.
금지사항
맞춤 장소 컨테이너 내에 광고, 마케팅 문구, 프로모션 할인 또는 정기 결제 메시지를 포함하지 마세요.
고급 장소 세부정보 예시
장소 이름 생략
장소 이름을 생략하려면AdvancedPlaceDetailsConfiguration의 content 매개변수에 .name를 포함하지 마세요.
Swift
struct DemoView: View { static let peetsCoffeePlaceID = "ChIJT7FdmYiAhYAROFOvrIxRJDU" // Query for loading the place details component. @State var query: PlaceDetailsQuery = PlaceDetailsQuery( identifier: .placeID(peetsCoffeePlaceID) ) @State private var favoritePlaces: Set<String> = [] var body: some View { AdvancedPlaceDetailsView( query: $query, configuration: AdvancedPlaceDetailsConfiguration( content:[.address()], theme: PlacesMaterialTheme() ), placeDetailsCallback: { result in if let place = result.place { print("Place: \(place.description)") } else { print("Error: \(String(describing: result.error))") } } ) } }
작업 버튼 삭제
Swift
struct DemoView: View { static let peetsCoffeePlaceID = "ChIJT7FdmYiAhYAROFOvrIxRJDU" @State var query: PlaceDetailsQuery = PlaceDetailsQuery( identifier: .placeID(peetsCoffeePlaceID) ) var body: some View { AdvancedPlaceDetailsView( query: $query, configuration: AdvancedPlaceDetailsConfiguration( content: AdvancedPlaceDetailsView.allContent, theme: PlacesMaterialTheme() ), placeDetailsCallback: { result in if let place = result.place { print("Place: \(place.description)") } else { print("Error: \(String(describing: result.error))") } } ) .mainActions{ _ in return [] } } }
맞춤 및 사전 정의된 작업 추가
이 샘플은 사전 정의된 지도에서 열기 작업과 함께 사용자가 장소를 즐겨찾기에 추가하거나 즐겨찾기에서 삭제할 수 있는 옵션을 추가합니다.
Swift
struct DemoView: View { static let peetsCoffeePlaceID = "ChIJT7FdmYiAhYAROFOvrIxRJDU" @State var query: PlaceDetailsQuery = PlaceDetailsQuery( identifier: .placeID(peetsCoffeePlaceID) ) @State var favoritePlaces: Set<String> = [] var body: some View { AdvancedPlaceDetailsView( query: $query, configuration: AdvancedPlaceDetailsConfiguration( content: AdvancedPlaceDetailsView.allContent, theme: PlacesMaterialTheme() ), placeDetailsCallback: { result in if let place = result.place { print("Place: \(place.description)") } else { print("Error: \(String(describing: result.error))") } } ) .mainActions{ place in var actions: [MainPlaceActionElement] = [] let placeID = place.placeID! if self.favoritePlaces.contains(placeID) { actions.append( .action( MainPlaceAction( image: Image(systemName: "heart.fill"), label: "Unfavorite" ) { _ in self.toggleFavorite(placeID) } ) ) } else { actions.append( .action( MainPlaceAction( image: Image(systemName: "heart"), label: "Favorite" ) { _ in self.toggleFavorite(placeID) } ) ) } actions.append(.actionId(.openMap(style: .primary))) return actions } .cornerActions { place in var actions: [CornerPlaceActionElement] = [] let placeID = place.placeID! if self.favoritePlaces.contains(placeID) { actions.append( .action( CornerPlaceAction( image: Image(systemName: "heart.fill"), accessibilityLabel: "Unfavorite", ) { _ in self.toggleFavorite(placeID) } ) ) } else { actions.append( .action( CornerPlaceAction( image: Image(systemName: "heart"), accessibilityLabel: "Favorite", ) { _ in self.toggleFavorite(placeID) } ) ) } actions.append(.actionId(.openMap(style: .primary))) return actions } } func toggleFavorite(_ placeID: String) { if favoritePlaces.contains(placeID) { favoritePlaces.remove(placeID) } else { favoritePlaces.insert(placeID) } } }
리뷰 및 미디어 필터링
이 코드 샘플은 '커피'를 언급하는 미디어와 리뷰만 보여줍니다.
Swift
struct DemoView: View { static let peetsCoffeePlaceID = "ChIJT7FdmYiAhYAROFOvrIxRJDU" @State var query: PlaceDetailsQuery = PlaceDetailsQuery( identifier: .placeID(peetsCoffeePlaceID) ) let searchMediaOptions = SearchMediaOptions(query: "coffee") let searchReviewsOptions = SearchReviewsOptions(query: "coffee") var body: some View { AdvancedPlaceDetailsView( query: $query, configuration: AdvancedPlaceDetailsConfiguration( content: [.media(), .reviews()], theme: PlacesMaterialTheme() ), placeDetailsCallback: { _ in } ) .searchMediaOptions(searchMediaOptions) { results in guard let result = results.first else { return } switch result { case .success(let summary): print("Summary: \(summary)") case .failure(let error): print("Error: \(error)") } } .searchReviewsOptions(searchReviewsOptions) { results in guard let result = results.first else { return } switch result { case .success(let summary): print("Summary: \(summary)") case .failure(let error): print("Error: \(error)") } } } }
콘텐츠 슬롯 만들기
이 샘플은 basicSectionTop 및 basicSectionBottom 슬롯에 콘텐츠를 추가합니다.
Swift
import SwiftUI import PlacesSwift struct ItineraryCard: View { static let peetsCoffeePlaceID = "ChIJT7FdmYiAhYAROFOvrIxRJDU" @State var query: PlaceDetailsQuery = PlaceDetailsQuery( identifier: .placeID(peetsCoffeePlaceID) ) var body: some View { AdvancedPlaceDetailsCompactView( orientation: .vertical, query: $query, configuration: AdvancedPlaceDetailsCompactConfiguration( content: AdvancedPlaceDetailsCompactView.allContent, theme: PlacesMaterialTheme() ), placeDetailsCallback: { _ in } ) .placeDetailsCompactContentSlot(position: .basicSectionTop) { place in Text("Day 2 • 2:30 PM") .font(.caption) .fontWeight(.bold) .foregroundColor(.accentColor) } .placeDetailsCompactContentSlot(position: .basicSectionBottom) { place in VStack(alignment: .leading, spacing: 4) { Text("AI Notes") .font(.caption) .bold() Text("Great quiet atmosphere for morning meetings. Famous for house-roasted pour-overs.") .font(.footnote) .foregroundColor(.secondary) } .padding(8) .background(Color(.systemGray6)) .cornerRadius(8) } } }