Komponent zaawansowanych informacji o miejscu

Wersja Advanced komponentu Informacje o miejscu oferuje te same funkcje co Places Details Essentials. Możesz też wybrać, czy ma być wyświetlana nazwa miejsca, skonfigurować przyciski poleceń komponentu oraz zastosować opcje wyszukiwania i filtrowania do wyświetlanych opinii i multimediów.

Zaawansowana konfiguracja informacji o miejscu

Aby uzyskać dostęp do funkcji zaawansowanych, użyj AdvancedPlaceDetailsView lub AdvancedPlaceDetailsCompactView.

Opcje wyświetlania treści

Możesz określić, które treści mają być wyświetlane, używając typów wyliczeniowych w AdvancedPlaceDetailsContent. Możesz skonfigurować wszystkie te same treści co w przypadku podstawowych informacji o miejscu, a także wybrać, czy ma być wyświetlana nazwa miejsca.

Konfigurowanie przycisków poleceń

Aby usunąć lub dostosować przyciski poleceń, użyj metod .cornerActions i .mainActions interfejsu AdvancedPlaceDetailsView lub AdvancedPlaceDetailsCompactView.

Wymagania dotyczące podania źródła wizualnego

Widok kompaktowy informacji o miejscu z przyciskami konfigurowalnymi
Zaawansowany widok kompaktowy szczegółowych informacji o miejscu z przyciskiem konfigurowalnym

Ważne: musisz wyraźnie poinformować użytkowników, kiedy niestandardowy przycisk polecenia będzie udostępniać informacje o użytkowniku firmie innej niż Google. Zobacz wymagania dotyczące podania źródła wizualnego.

Przykład po prawej stronie pokazuje niestandardowy obraz, który wyraźnie informuje, że dane użytkownika zostaną wysłane do firmy „Altostrat”.

Stosowanie opcji wyszukiwania i filtrowania

Użyj metod .searchMediaOptions i .searchReviewOptions w AdvancedPlaceDetailsView lub AdvancedPlaceDetailsCompactView, aby włączyć wyszukiwanie i filtrowanie multimediów lub opinii.

Tworzenie niestandardowych boksów treści

Opcje umieszczania niestandardowych boksów na treści

Niestandardowe boksy na treści umożliwiają dodawanie własnych treści (takich jak podsumowania wygenerowane przez AI, sygnatury czasowe planu podróży lub niestandardowe plakietki) bezpośrednio do wstępnie zdefiniowanych stref układu.

Aby dodać niestandardowe treści, użyj metody .placeDetailsCompactContentSlot klasy AdvancedPlaceDetailsCompactView. Dostępne pozycje to .basicSectionTop i .basicSectionBottom.

Wymagania dotyczące podania źródła i sugestie dotyczące treści w boksach treści

Po zamontowaniu niestandardowego boksu na treści komunikat jest automatycznie aktualizowany, aby wyjaśnić, które treści są dostarczane przez Google, a które przez osoby trzecie.

Należy

Zachowaj wyraźną hierarchię wizualną między informacjami o miejscu w Google a treściami niestandardowymi, aby uniknąć niejasności co do źródła informacji.

Unikanie niejednoznaczności dotyczącej źródła informacji

Należy

Rozważ dostarczanie zlokalizowanych, wartościowych informacji dostosowanych do bezpośrednich celów użytkowników. Dostosowane treści, takie jak okna rezerwacji w czasie rzeczywistym lub aktualna dostępność, pomagają użytkownikom szybciej podejmować bardziej świadome decyzje.

Dostarczanie cennych statystyk

Nie

Nie powielaj istniejących informacji o miejscu w Google, takich jak oceny, opinie czy godziny otwarcia, nawet jeśli ukryjesz treści dostarczane przez Google. Może to wprowadzać użytkowników w błąd co do źródła treści i tego, czy pochodzą one od Google czy od innej firmy.

Nie duplikuj istniejących informacji o miejscu w Google.

Nie

Nie wyświetlaj nieprzypisanych twierdzeń ani plakietek (np. „Najlepsza rekomendacja!”), które mogą być mylone z oficjalnymi rekomendacjami Google. Treści niestandardowe muszą wyraźnie wskazywać źródło.

Nie wyświetlaj twierdzeń ani odznak bez podania źródła

Przeciwwskazania

Nie umieszczaj w kontenerach niestandardowych miejsc reklam, tekstów marketingowych, rabatów promocyjnych ani próśb o subskrypcję.

Nie dodawaj reklam, tekstów marketingowych, rabatów promocyjnych ani próśb o subskrypcję.

Przykłady zaawansowanych informacji o miejscu

pominąć nazwę miejsca,

Aby pominąć nazwę miejsca, nie uwzględniaj .name w parametrze content w AdvancedPlaceDetailsConfiguration.

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))")
        }
      }
    )
  }
}

Usuwanie przycisków poleceń

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 []
    }
  }
}

Dodawanie działań niestandardowych i wstępnie zdefiniowanych

Ten przykład dodaje opcję dodawania miejsca do ulubionych lub usuwania go z ulubionych, a także wstępnie zdefiniowane działanie Otwórz w Mapach.

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)
    }
  }
}

Filtrowanie opinii i multimediów

Ten przykładowy kod pokazuje tylko multimedia i opinie, które zawierają słowo „kawa”.

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)")
      }
    }
  }
}

Tworzenie boksów treści

Ten przykład dodaje treści do boksów basicSectionTop i 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)
      }
    }
}