مكوّن "تفاصيل المكان المتقدّمة"

يوفّر الإصدار المتقدّم من مكوّن "تفاصيل المكان" الميزات نفسها التي يوفّرها Places Details Essentials. يتيح لك هذا القسم أيضًا اختيار ما إذا كان سيتم عرض اسم المكان، وضبط أزرار الإجراءات الخاصة بالمكوّن، وتطبيق خيارات البحث والتصفية على المراجعات والوسائط المعروضة.

إعدادات متقدّمة لتفاصيل الأماكن

استخدام AdvancedPlaceDetailsView أو AdvancedPlaceDetailsCompactView للوصول إلى الميزات المتقدّمة

خيارات عرض المحتوى

يمكنك تحديد المحتوى الذي تريد عرضه باستخدام القيم التعدادية في AdvancedPlaceDetailsContent. يمكنك ضبط كل المحتوى نفسه الذي يظهر في أساسيات تفاصيل الأماكن، بالإضافة إلى اختيار ما إذا كان سيتم عرض اسم المكان.

ضبط أزرار الإجراءات

استخدِم طريقتَي .cornerActions و.mainActions في AdvancedPlaceDetailsView أو AdvancedPlaceDetailsCompactView لإزالة أزرار الإجراءات أو تخصيصها.

متطلبات تحديد المصدر المرئي

العرض المكثّف لتفاصيل المكان مع أزرار مخصّصة
عرض مصغّر لتفاصيل المكان المتقدّمة مع زرّ مخصّص

ملاحظة مهمة: يجب أن توضّح للمستخدمين النهائيين الحالات التي سيشارك فيها زر الإجراء المخصّص معلومات المستخدم مع جهة خارجية غير Google. راجِع متطلبات الإشارة إلى المصدر المرئي.

يعرض المثال على اليسار صورة مخصّصة توضّح أنّه سيتم إرسال معلومات المستخدم إلى "Altostrat".

تطبيق خيارات البحث والفلترة

استخدِم الطريقتَين .searchMediaOptions و.searchReviewOptions من AdvancedPlaceDetailsView أو AdvancedPlaceDetailsCompactView لتفعيل البحث عن الوسائط أو المراجعات وفلترتها.

إنشاء خانات محتوى مخصّصة

خيارات مواضع إعلانات مخصّصة

تتيح لك خانات المحتوى المخصّصة إضافة المحتوى الخاص بك (مثل الملخّصات من إنشاء الذكاء الاصطناعي أو الطوابع الزمنية لبرنامج الرحلة أو الشارات المخصّصة) مباشرةً إلى مناطق التنسيق المحدّدة مسبقًا.

لإضافة محتوى مخصّص، استخدِم طريقة .placeDetailsCompactContentSlot في AdvancedPlaceDetailsCompactView. الوظيفتان المتاحتان هما .basicSectionTop و.basicSectionBottom.

متطلبات تحديد المصدر واقتراحات المحتوى لمساحات عرض المحتوى

عند تحميل موضع إعلان مخصّص، يتم تعديل بيان الإفصاح تلقائيًا لتوضيح المحتوى الذي تقدّمه Google والمحتوى الذي تقدّمه جهات خارجية.

الإجراءات المقترَحة

الحفاظ على تسلسل هرمي مرئي واضح بين تفاصيل "المكان على Google" والمحتوى المخصّص لمنع أي غموض بشأن مصدر المعلومات

تجنُّب الغموض بشأن مصدر المعلومات

الإجراءات المقترَحة

ننصحك بتقديم إحصاءات محلية عالية القيمة ومخصّصة لتلبية أهداف المستخدمين المباشرة، لأنّ المحتوى المخصّص، مثل فترات الحجز في الوقت الفعلي أو مدى التوفّر الحالي، يساعد المستخدمين في اتّخاذ قرارات أسرع وأكثر استنارة.

تقديم إحصاءات قيّمة

ما ننصحك بتجنّبه

لا تكرّر تفاصيل "أماكن Google" الحالية، مثل التقييمات أو المراجعات أو ساعات العمل، حتى إذا أخفيت المحتوى المقدَّم من Google. قد يؤدي ذلك إلى إرباك المستخدمين بشأن مصدر المحتوى وما إذا كان من Google أو من جهة خارجية.

عدم تكرار تفاصيل الأماكن الحالية على Google

ما ننصحك بتجنّبه

لا تعرض ادّعاءات أو شارات بدون مصدر (مثل "أفضل اقتراح!") يمكن أن يتم الخلط بينها وبين تأييدات Google الرسمية. يجب أن يذكر المحتوى المخصّص مصدره بوضوح.

عدم عرض ادّعاءات أو شارات بدون مصدر

ما ننصحك بتجنّبه

لا تضمِّن إعلانات أو نصوصًا تسويقية أو خصومات ترويجية أو طلبات اشتراك في حاويات الأماكن المخصّصة.

لا تضمِّن إعلانات أو نصوصًا تسويقية أو خصومات ترويجية أو طلبات اشتراك

أمثلة على "تفاصيل المكان المتقدّمة"

حذف اسم المكان

لإغفال اسم المكان، لا تُدرِج .name في المَعلمة content من 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))")
        }
      }
    )
  }
}

إزالة أزرار الإجراءات

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

إضافة إجراءات مخصّصة ومحدَّدة مسبقًا

يضيف هذا النموذج خيارًا للمستخدم لتفضيل مكان أو إزالة تفضيله، بالإضافة إلى الإجراء الفتح في "خرائط Google" المحدّد مسبقًا.

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