کامپوننت جزئیات مکان پیشرفته

نسخه پیشرفته کامپوننت Place Details همان ویژگی‌های Places Details Essentials را ارائه می‌دهد. همچنین به شما امکان می‌دهد انتخاب کنید که آیا نام مکان نمایش داده شود یا خیر، دکمه‌های عملیاتی کامپوننت را پیکربندی کنید و گزینه‌های جستجو و فیلتر را برای نظرات و رسانه‌های نمایش داده شده اعمال کنید.

پیکربندی پیشرفته جزئیات مکان

برای دسترسی به ویژگی‌های پیشرفته، AdvancedPlaceDetailsView یا AdvancedPlaceDetailsCompactView استفاده کنید.

گزینه‌های نمایش محتوا

شما می‌توانید با استفاده از enumها در AdvancedPlaceDetailsContent مشخص کنید که کدام محتوا نمایش داده شود. می‌توانید تمام محتوای مشابه Places Details Essentials را پیکربندی کنید، و همچنین انتخاب کنید که آیا نام Place نمایش داده شود یا خیر.

پیکربندی دکمه‌های عملیاتی

از متدهای .cornerActions ‎ و .mainActions ‎ از AdvancedPlaceDetailsView یا AdvancedPlaceDetailsCompactView برای حذف یا سفارشی‌سازی دکمه‌های عملیاتی استفاده کنید.

الزامات انتساب بصری

جزئیات را با دکمه‌های سفارشی، نمای فشرده قرار دهید
نمای فشرده جزئیات مکان پیشرفته با دکمه سفارشی

مهم: شما باید برای کاربران نهایی روشن کنید که چه زمانی یک دکمه اقدام سفارشی، اطلاعات کاربر را با شخص ثالثی غیر از گوگل به اشتراک می‌گذارد. به الزامات انتساب بصری مراجعه کنید.

مثال سمت راست یک تصویر سفارشی را نشان می‌دهد که به وضوح نشان می‌دهد اطلاعات کاربر به «Altostrat» ارسال خواهد شد.

اعمال گزینه‌های جستجو و فیلتر

برای فعال کردن جستجو و فیلتر کردن رسانه‌ها یا نظرات، از متدهای .searchMediaOptions ‎ و .searchReviewOptions ‎ از AdvancedPlaceDetailsView ‎ یا AdvancedPlaceDetailsCompactView ‎ استفاده کنید.

ایجاد اسلات‌های محتوای سفارشی

گزینه‌های سفارشی برای قرار دادن اسلات محتوا

اسلات‌های محتوای سفارشی به شما امکان می‌دهند محتوای خود (مانند خلاصه‌های تولید شده توسط هوش مصنوعی، مهرهای زمانی برنامه سفر یا نشان‌های سفارشی) را مستقیماً به مناطق طرح‌بندی از پیش تعریف شده اضافه کنید.

برای افزودن محتوای سفارشی، از متد .placeDetailsCompactContentSlot از AdvancedPlaceDetailsCompactView استفاده کنید. موقعیت‌های موجود عبارتند از .basicSectionTop و .basicSectionBottom .

الزامات انتساب و پیشنهادهای محتوا برای بخش‌های محتوایی

وقتی یک جایگاه محتوای سفارشی ایجاد می‌شود، این افشا به‌طور خودکار به‌روزرسانی می‌شود تا مشخص شود کدام محتوا توسط گوگل ارائه شده و برخی محتوا توسط اشخاص ثالث ارائه شده است.

انجام دهید

برای جلوگیری از هرگونه ابهام در مورد منبع اطلاعات، سلسله مراتب بصری واضحی را بین جزئیات Google Place و محتوای سفارشی حفظ کنید.

جلوگیری از ابهام در مورد منبع اطلاعات

انجام دهید

بینش‌های محلی و ارزشمند متناسب با اهداف فوری کاربران خود را در نظر بگیرید. محتوای متناسب مانند پنجره‌های رزرو در لحظه یا موجودی فعلی به کاربران کمک می‌کند تا تصمیمات سریع‌تر و آگاهانه‌تری بگیرند.

ارائه بینش‌های ارزشمند

نکن

حتی اگر محتوای ارائه شده توسط گوگل را پنهان کرده‌اید، جزئیات موجود در گوگل پلیس، مانند رتبه‌بندی‌ها، نظرات یا ساعات کاری را کپی نکنید. انجام این کار می‌تواند کاربران را در مورد منبع محتوا و اینکه آیا از گوگل یا شخص ثالث است، گیج کند.

جزئیات موجود در Google Place را کپی نکنید

نکن

ادعاها یا نشان‌های بدون منبع (مثلاً «توصیه برتر!») را که ممکن است با تأییدیه‌های رسمی گوگل اشتباه گرفته شوند، نمایش ندهید. محتوای سفارشی باید صریحاً منبع خود را ذکر کند.

ادعاها یا نشان‌های نامشخص را نمایش ندهید

نکن

تبلیغات، متن بازاریابی، تخفیف‌های تبلیغاتی یا درخواست‌های اشتراک را در جعبه‌های سفارشی قرار ندهید.

تبلیغات، متن بازاریابی، تخفیف‌های تبلیغاتی یا درخواست‌های اشتراک را درج نکنید

مثال‌های جزئیات مکان پیشرفته

نام مکان را حذف کنید

برای حذف نام مکان، در پارامتر content AdvancedPlaceDetailsConfiguration از .name استفاده نکنید.

سویفت

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

حذف دکمه‌های عملیاتی

سویفت

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

افزودن اقدامات سفارشی و از پیش تعریف شده

این نمونه، به همراه عملکرد از پیش تعریف‌شده‌ی «باز کردن در نقشه‌ها» ، گزینه‌ای را برای کاربر اضافه می‌کند تا بتواند یک مکان را به لیست علاقه‌مندی‌ها اضافه کند یا از لیست علاقه‌مندی‌ها حذف کند.

سویفت

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

فیلتر کردن نظرات و رسانه‌ها

این نمونه کد فقط رسانه‌ها و نقدهایی را نشان می‌دهد که به «قهوه» اشاره کرده‌اند.

سویفت

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 اضافه می‌کند.

سویفت

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