expo-gaode-map-navigation 1.1.2-next.0 → 1.1.2-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,16 +4,20 @@ import android.annotation.SuppressLint
4
4
  import android.content.Context
5
5
  import android.os.Bundle
6
6
  import android.util.Log
7
+ import android.view.View
8
+ import android.view.ViewGroup
7
9
  import com.amap.api.navi.AMapNavi
8
10
  import com.amap.api.navi.AMapNaviListener
9
11
  import com.amap.api.navi.AMapNaviView
10
12
  import com.amap.api.navi.AMapNaviViewListener
11
13
  import com.amap.api.navi.AMapNaviViewOptions
14
+ import com.amap.api.navi.enums.MapStyle
12
15
  import com.amap.api.navi.enums.NaviType
13
16
  import com.amap.api.navi.model.*
14
17
  import expo.modules.kotlin.AppContext
15
18
  import expo.modules.kotlin.viewevent.EventDispatcher
16
19
  import expo.modules.kotlin.views.ExpoView
20
+ import java.util.IdentityHashMap
17
21
 
18
22
  @SuppressLint("ViewConstructor")
19
23
  @Suppress("DEPRECATION", "OVERRIDE_DEPRECATION")
@@ -38,11 +42,36 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
38
42
  internal var showCamera: Boolean = true
39
43
  internal var naviType: Int = NaviType.GPS
40
44
  internal var enableVoice: Boolean = true
41
-
45
+
46
+
47
+ internal var androidStatusBarPaddingTopDp: Double? = null
48
+
49
+ internal var showUIElements: Boolean = true
50
+ internal var androidTrafficBarEnabled: Boolean = true
51
+ internal var isRouteListButtonShow: Boolean = true
52
+ internal var isTrafficLayerEnabled: Boolean = true
53
+ internal var autoChangeZoom : Boolean = true
54
+ internal var autoLockCar: Boolean = true
55
+ internal var isTrafficLine: Boolean = true
56
+ internal var isRealCrossDisplayShow : Boolean = true
57
+ internal var isNaviArrowVisible : Boolean = true
58
+ internal var isAfterRouteAutoGray: Boolean = false
59
+ internal var isVectorLineShow: Boolean = true
42
60
  private val naviView: AMapNaviView = AMapNaviView(context)
43
61
  private var aMapNavi: AMapNavi? = null
44
62
  private var startCoordinate: NaviLatLng? = null
45
63
  private var endCoordinate: NaviLatLng? = null
64
+
65
+ private var lastAppliedTopPaddingPx: Int? = null
66
+
67
+ private var topInsetPx: Int = 0
68
+ private var overlayHooked: Boolean = false
69
+ private val overlayStates = IdentityHashMap<View, OverlayState>()
70
+
71
+ private data class OverlayState(
72
+ val translationY: Float,
73
+ val paddingTop: Int
74
+ )
46
75
 
47
76
  // 导航监听器
48
77
  @Suppress("DEPRECATION", "OVERRIDE_DEPRECATION")
@@ -270,7 +299,18 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
270
299
  try {
271
300
  // 初始化导航视图
272
301
  naviView.onCreate(Bundle())
302
+ naviView.layoutParams = android.widget.FrameLayout.LayoutParams(
303
+ android.widget.FrameLayout.LayoutParams.MATCH_PARENT,
304
+ android.widget.FrameLayout.LayoutParams.MATCH_PARENT
305
+ )
273
306
  addView(naviView)
307
+
308
+ clipChildren = false
309
+ clipToPadding = false
310
+ naviView.clipChildren = false
311
+ naviView.clipToPadding = false
312
+
313
+ ensureOverlayInsetHook()
274
314
 
275
315
  // 使用单例获取导航实例
276
316
  aMapNavi = AMapNavi.getInstance(context.applicationContext)
@@ -285,20 +325,20 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
285
325
  // === 基础界面控制 ===
286
326
  // 注意:isLayoutVisible 控制整个导航UI布局的显示
287
327
  // 设置为 true 将显示导航信息面板(包括距离、时间等)
288
- options.isLayoutVisible = true // ⭐ 显示导航界面布局(包括导航信息面板)
328
+ options.isLayoutVisible = showUIElements
289
329
  options.isSettingMenuEnabled = true // 显示设置菜单按钮
290
330
  options.isCompassEnabled = true // 显示指南针
291
- options.isTrafficBarEnabled = true // 显示交通路况光柱条(顶部)
292
- options.isRouteListButtonShow = true // 显示路线全览按钮
293
-
331
+ options.isTrafficBarEnabled = androidTrafficBarEnabled // 显示路况条
332
+ options.isRouteListButtonShow = isRouteListButtonShow // 显示路线全览按钮
333
+
294
334
  Log.d("ExpoGaodeMapNaviView", "导航UI配置: isLayoutVisible=true, 所有UI元素已启用")
295
335
 
296
336
  // === 地图图层 ===
297
- options.isTrafficLayerEnabled = true // 显示交通路况图层
298
- options.isTrafficLine = true // 显示交通路况线
337
+ options.isTrafficLayerEnabled = isTrafficLayerEnabled // 显示交通路况图层
338
+ options.isTrafficLine = isTrafficLine // 显示交通路况线
299
339
 
300
340
  // === 路口放大图和车道信息 ===
301
- options.isRealCrossDisplayShow = true // 显示实景路口放大图
341
+ options.isRealCrossDisplayShow = isRealCrossDisplayShow // 显示实景路口放大图
302
342
  options.setModeCrossDisplayShow(true) // 显示路口3D模型(使用方法而非属性)
303
343
  options.isLaneInfoShow = true // 显示车道信息
304
344
  options.isEyrieCrossDisplay = true // 显示鹰眼路口图
@@ -310,32 +350,36 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
310
350
 
311
351
  // === 路线和导航箭头 ===
312
352
  options.isAutoDrawRoute = true // 自动绘制路线
313
- options.isNaviArrowVisible = true // 显示导航箭头
353
+ options.isNaviArrowVisible = isNaviArrowVisible // 显示导航箭头
314
354
  options.isSecondActionVisible = true // 显示辅助操作(如下个路口提示)
315
355
  options.isDrawBackUpOverlay = true // 绘制备用路线覆盖物
356
+ if(isVectorLineShow)
357
+ options.isLeaderLineEnabled
316
358
 
317
359
  // === 地图锁车和视角控制 ===
318
- options.isAutoLockCar = true // 自动锁车
360
+ options.isAutoLockCar = autoLockCar // 自动锁车
319
361
  options.lockMapDelayed = 5000L // 5秒后自动锁车(毫秒)
320
- options.setAutoDisplayOverview(false) // 不自动显示全览
321
- options.isAutoChangeZoom = true // 根据导航自动调整缩放级别
322
- options.setZoom(18) // 锁车时的缩放级别 (14-18)
323
- options.setTilt(35) // 锁车时的倾斜角度 (0-60)
362
+ options.isAutoDisplayOverview = false // 不自动显示全览
363
+ options.isAutoChangeZoom = autoChangeZoom // 根据导航自动调整缩放级别
364
+ options.zoom = 18 // 锁车时的缩放级别 (14-18)
365
+ options.tilt = 35 // 锁车时的倾斜角度 (0-60)
324
366
 
325
367
  // === 已走路线处理 ===
326
- options.setAfterRouteAutoGray(true) // 走过的路线自动变灰
368
+ options.isAfterRouteAutoGray = isAfterRouteAutoGray // 走过的路线自动变灰
327
369
 
328
370
  // === 传感器和定位 ===
329
- options.setSensorEnable(true) // 使用设备传感器
371
+ options.isSensorEnable = true // 使用设备传感器
330
372
 
331
373
  // === 夜间模式(已废弃但保留兼容) ===
332
374
  // 建议使用 setMapStyle 方法设置地图样式
333
- options.setAutoNaviViewNightMode(false) // 不自动切换夜间模式
375
+ options.isAutoNaviViewNightMode = false // 不自动切换夜间模式
334
376
 
335
377
  // === 鹰眼地图 ===
336
- options.setEagleMapVisible(false) // 不显示鹰眼地图(小地图)
378
+ options.isEagleMapVisible = false // 不显示鹰眼地图(小地图)
337
379
 
338
380
  naviView.viewOptions = options
381
+
382
+ naviView.post { updateTopInsetPadding() }
339
383
 
340
384
  // 设置导航视图监听器
341
385
  naviView.setAMapNaviViewListener(object : AMapNaviViewListener {
@@ -364,6 +408,323 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
364
408
  }
365
409
  }
366
410
 
411
+ private fun getStatusBarHeightPx(): Int {
412
+ return try {
413
+ val resourceId = context.resources.getIdentifier("status_bar_height", "dimen", "android")
414
+ if (resourceId > 0) context.resources.getDimensionPixelSize(resourceId) else 0
415
+ } catch (_: Exception) {
416
+ 0
417
+ }
418
+ }
419
+
420
+ private fun dpToPx(dp: Double): Int {
421
+ val density = context.resources.displayMetrics.density
422
+ return (dp * density + 0.5).toInt()
423
+ }
424
+
425
+ private fun updateTopInsetPadding() {
426
+ val shouldApplyPadding = androidStatusBarPaddingTopDp != null
427
+ val paddingTopPx = if (shouldApplyPadding) {
428
+ androidStatusBarPaddingTopDp?.let { dpToPx(it) } ?: getStatusBarHeightPx()
429
+ } else {
430
+ //默认返回状态栏高度
431
+ getStatusBarHeightPx()
432
+ }
433
+
434
+ if (lastAppliedTopPaddingPx == paddingTopPx) {
435
+ return
436
+ }
437
+
438
+ lastAppliedTopPaddingPx = paddingTopPx
439
+
440
+ topInsetPx = paddingTopPx
441
+
442
+ naviView.setPadding(0, 0, 0, 0)
443
+
444
+ applyTopInsetToOverlays(paddingTopPx)
445
+ }
446
+
447
+ private fun ensureOverlayInsetHook() {
448
+ if (overlayHooked) {
449
+ return
450
+ }
451
+
452
+ overlayHooked = true
453
+ naviView.addOnLayoutChangeListener { _, _, _, _, _, _, _, _, _ ->
454
+ applyTopInsetToOverlays(topInsetPx)
455
+ }
456
+ }
457
+
458
+ private fun applyTopInsetToOverlays(paddingTopPx: Int) {
459
+ if (paddingTopPx <= 0) {
460
+ if (overlayStates.isNotEmpty()) {
461
+ val iterator = overlayStates.entries.iterator()
462
+ while (iterator.hasNext()) {
463
+ val entry = iterator.next()
464
+ val view = entry.key
465
+ val state = entry.value
466
+ view.translationY = state.translationY
467
+ view.setPadding(view.paddingLeft, state.paddingTop, view.paddingRight, view.paddingBottom)
468
+ iterator.remove()
469
+ }
470
+ }
471
+ return
472
+ }
473
+
474
+ val rawTargets = findTopOverlayTargets(naviView)
475
+ val targets = filterTopLevelTargets(naviView, rawTargets)
476
+ if (targets.isEmpty()) {
477
+ val applied = applyTopPaddingToNaviUiLayer(paddingTopPx)
478
+ if (!applied) {
479
+ naviView.post { applyTopPaddingToNaviUiLayer(paddingTopPx) }
480
+ }
481
+ return
482
+ }
483
+
484
+ val targetSet = targets.toHashSet()
485
+
486
+ val iterator = overlayStates.entries.iterator()
487
+ while (iterator.hasNext()) {
488
+ val entry = iterator.next()
489
+ val view = entry.key
490
+ if (!targetSet.contains(view)) {
491
+ val state = entry.value
492
+ view.translationY = state.translationY
493
+ view.setPadding(view.paddingLeft, state.paddingTop, view.paddingRight, view.paddingBottom)
494
+ iterator.remove()
495
+ }
496
+ }
497
+
498
+ for (target in targets) {
499
+ if (!overlayStates.containsKey(target)) {
500
+ overlayStates[target] = OverlayState(
501
+ translationY = target.translationY,
502
+ paddingTop = target.paddingTop
503
+ )
504
+ }
505
+ ensureNoClipChain(target)
506
+ target.translationY = paddingTopPx.toFloat()
507
+ }
508
+ }
509
+
510
+ private fun ensureNoClipChain(view: View) {
511
+ var currentParent = view.parent
512
+ while (currentParent is ViewGroup) {
513
+ currentParent.clipChildren = false
514
+ currentParent.clipToPadding = false
515
+ if (currentParent === naviView) {
516
+ break
517
+ }
518
+ currentParent = currentParent.parent
519
+ }
520
+ }
521
+
522
+ private fun filterTopLevelTargets(root: ViewGroup, targets: List<View>): List<View> {
523
+ if (targets.size <= 1) {
524
+ return targets
525
+ }
526
+
527
+ val set = targets.toHashSet()
528
+ val result = ArrayList<View>(targets.size)
529
+ for (view in targets) {
530
+ var parent = view.parent
531
+ var hasAncestorInTargets = false
532
+ while (parent is View) {
533
+ if (parent === root) {
534
+ break
535
+ }
536
+ if (set.contains(parent)) {
537
+ hasAncestorInTargets = true
538
+ break
539
+ }
540
+ parent = parent.parent
541
+ }
542
+ if (!hasAncestorInTargets) {
543
+ result.add(view)
544
+ }
545
+ }
546
+
547
+ return result
548
+ }
549
+
550
+ private fun findTopOverlayTargets(root: ViewGroup): List<View> {
551
+ val result = ArrayList<View>()
552
+ val parentHeight = root.height
553
+ val parentWidth = root.width
554
+ if (parentHeight <= 0 || parentWidth <= 0) {
555
+ return result
556
+ }
557
+
558
+ val queue = ArrayDeque<View>()
559
+ for (i in 0 until root.childCount) {
560
+ queue.add(root.getChildAt(i))
561
+ }
562
+
563
+ while (queue.isNotEmpty()) {
564
+ val view = queue.removeFirst()
565
+ val group = view as? ViewGroup
566
+ if (group != null) {
567
+ for (i in 0 until group.childCount) {
568
+ queue.add(group.getChildAt(i))
569
+ }
570
+ }
571
+
572
+ if (!view.isShown) {
573
+ continue
574
+ }
575
+
576
+ val name = view.javaClass.name
577
+ if (name.contains("MapView", ignoreCase = true) ||
578
+ name.contains("Texture", ignoreCase = true) ||
579
+ name.contains("Surface", ignoreCase = true) ||
580
+ name.contains("GLSurface", ignoreCase = true)
581
+ ) {
582
+ continue
583
+ }
584
+
585
+ if (view.height <= 0 || view.width <= 0) {
586
+ continue
587
+ }
588
+
589
+ if (view.top > 1) {
590
+ continue
591
+ }
592
+
593
+ if (view.height >= (parentHeight * 0.6f).toInt()) {
594
+ continue
595
+ }
596
+
597
+ val wideEnough = view.width >= (parentWidth * 0.5f).toInt()
598
+ val likelyUi = wideEnough && (view.isClickable || (view as? ViewGroup)?.childCount ?: 0 > 0)
599
+ if (!likelyUi) {
600
+ continue
601
+ }
602
+
603
+ result.add(view)
604
+ }
605
+
606
+ return result
607
+ }
608
+
609
+ private fun applyTopPaddingToNaviUiLayer(paddingTopPx: Int): Boolean {
610
+ val uiRoot = findNaviUiRoot(naviView) ?: return false
611
+
612
+ uiRoot.setPadding(uiRoot.paddingLeft, paddingTopPx, uiRoot.paddingRight, uiRoot.paddingBottom)
613
+ uiRoot.clipToPadding = false
614
+ return true
615
+ }
616
+
617
+ private fun findNaviUiRoot(root: ViewGroup): ViewGroup? {
618
+ var best: ViewGroup? = null
619
+ var bestScore = Int.MIN_VALUE
620
+
621
+ val queue = ArrayDeque<View>()
622
+ for (i in 0 until root.childCount) {
623
+ queue.add(root.getChildAt(i))
624
+ }
625
+
626
+ while (queue.isNotEmpty()) {
627
+ val view = queue.removeFirst()
628
+ val group = view as? ViewGroup
629
+ if (group != null) {
630
+ val score = scoreAsUiRootCandidate(group)
631
+ if (score > bestScore) {
632
+ bestScore = score
633
+ best = group
634
+ }
635
+ for (i in 0 until group.childCount) {
636
+ queue.add(group.getChildAt(i))
637
+ }
638
+ }
639
+ }
640
+
641
+ return if (bestScore > 0) best else null
642
+ }
643
+
644
+ private fun scoreAsUiRootCandidate(group: ViewGroup): Int {
645
+ val name = group.javaClass.name
646
+ if (name.contains("MapView", ignoreCase = true) ||
647
+ name.contains("Texture", ignoreCase = true) ||
648
+ name.contains("Surface", ignoreCase = true) ||
649
+ name.contains("GLSurface", ignoreCase = true)
650
+ ) {
651
+ return Int.MIN_VALUE
652
+ }
653
+
654
+ var score = 0
655
+
656
+ val lp = group.layoutParams
657
+ if (lp != null) {
658
+ if (lp.width == ViewGroup.LayoutParams.MATCH_PARENT && lp.height == ViewGroup.LayoutParams.MATCH_PARENT) {
659
+ score += 4
660
+ } else if (lp.width == ViewGroup.LayoutParams.MATCH_PARENT) {
661
+ score += 2
662
+ }
663
+ }
664
+
665
+ if (group.childCount >= 3) {
666
+ score += 2
667
+ } else if (group.childCount >= 1) {
668
+ score += 1
669
+ }
670
+
671
+ if (name.contains("RelativeLayout", ignoreCase = true) || name.contains("FrameLayout", ignoreCase = true)) {
672
+ score += 1
673
+ }
674
+
675
+ return score
676
+ }
677
+
678
+
679
+
680
+ fun applyAndroidStatusBarPaddingTop(topDp: Double?) {
681
+ androidStatusBarPaddingTopDp = topDp
682
+ updateTopInsetPadding()
683
+ }
684
+
685
+ fun applyShowUIElements(visible: Boolean) {
686
+ showUIElements = visible
687
+ val options = naviView.viewOptions
688
+ options.isLayoutVisible = visible
689
+ naviView.viewOptions = options
690
+ }
691
+
692
+ fun applyAndroidTrafficBarEnabled(enabled: Boolean) {
693
+ androidTrafficBarEnabled = enabled
694
+ val options = naviView.viewOptions
695
+ options.isTrafficBarEnabled = enabled
696
+ naviView.viewOptions = options
697
+ }
698
+
699
+ fun applyShowTrafficButton(enabled: Boolean) {
700
+ isTrafficLayerEnabled = enabled
701
+ val options = naviView.viewOptions
702
+ options.isTrafficLayerEnabled = enabled
703
+ naviView.viewOptions = options
704
+ }
705
+
706
+ fun applyShowBrowseRouteButton(enabled: Boolean) {
707
+ isRouteListButtonShow = enabled
708
+ val options = naviView.viewOptions
709
+ options.isRouteListButtonShow = enabled
710
+ naviView.viewOptions = options
711
+ }
712
+
713
+ fun applyShowGreyAfterPass(enabled: Boolean){
714
+ isAfterRouteAutoGray = enabled
715
+ val options = naviView.viewOptions
716
+ options.isAfterRouteAutoGray = enabled
717
+ naviView.viewOptions = options
718
+ }
719
+
720
+ fun applyShowVectorline(enabled: Boolean){
721
+ isVectorLineShow = enabled
722
+ val options = naviView.viewOptions
723
+ if(enabled)
724
+ options.isLeaderLineEnabled
725
+ naviView.viewOptions = options
726
+ }
727
+
367
728
  fun startNavigation(startLat: Double, startLng: Double, endLat: Double, endLng: Double, promise: expo.modules.kotlin.Promise) {
368
729
  Log.d("ExpoGaodeMapNaviView", "startNavigation: $startLat, $startLng, $endLat, $endLng, naviType: $naviType")
369
730
  try {
@@ -454,24 +815,28 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
454
815
  }
455
816
 
456
817
  fun applyAutoLockCar(enabled: Boolean) {
818
+ autoLockCar = enabled
457
819
  val options = naviView.viewOptions
458
820
  options.isAutoLockCar = enabled
459
821
  naviView.viewOptions = options
460
822
  }
461
823
 
462
824
  fun applyAutoChangeZoom(enabled: Boolean) {
825
+ autoChangeZoom = enabled
463
826
  val options = naviView.viewOptions
464
827
  options.isAutoChangeZoom = enabled
465
828
  naviView.viewOptions = options
466
829
  }
467
830
 
468
831
  fun applyTrafficLayerEnabled(enabled: Boolean) {
832
+ isTrafficLine = enabled
469
833
  val options = naviView.viewOptions
470
- options.isTrafficLayerEnabled = enabled
834
+ options.isTrafficLine = enabled
471
835
  naviView.viewOptions = options
472
836
  }
473
837
 
474
838
  fun applyRealCrossDisplay(enabled: Boolean) {
839
+ isRealCrossDisplayShow = enabled
475
840
  val options = naviView.viewOptions
476
841
  options.isRealCrossDisplayShow = enabled
477
842
  naviView.viewOptions = options
@@ -491,6 +856,11 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
491
856
  // 夜间模式设置 - isNightMode 属性可能不存在
492
857
  try {
493
858
  val options = naviView.viewOptions
859
+ if(enabled){
860
+ options.setMapStyle(MapStyle.NIGHT, null)
861
+ }else{
862
+ options.setMapStyle(MapStyle.DAY, null)
863
+ }
494
864
  // options.isNightMode = enabled // 该属性可能不存在
495
865
  // 可以通过其他方式设置夜间模式
496
866
  naviView.viewOptions = options
@@ -586,8 +956,9 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
586
956
  */
587
957
  fun applyNaviArrowVisible(visible: Boolean) {
588
958
  try {
959
+ isNaviArrowVisible = visible
589
960
  val options = naviView.viewOptions
590
- options.setNaviArrowVisible(visible)
961
+ options.isNaviArrowVisible = visible
591
962
  naviView.viewOptions = options
592
963
  Log.d("ExpoGaodeMapNaviView", "Navi arrow visibility set to: $visible")
593
964
  } catch (e: Exception) {
@@ -649,4 +1020,4 @@ class ExpoGaodeMapNaviView(context: Context, appContext: AppContext) : ExpoView(
649
1020
  Log.e("ExpoGaodeMapNaviView", "Error destroying navi view", e)
650
1021
  }
651
1022
  }
652
- }
1023
+ }
@@ -101,7 +101,41 @@ class ExpoGaodeMapNaviViewModule : Module() {
101
101
  Prop<Boolean>("showTrafficLightView") { view, show ->
102
102
  view.applyShowTrafficLightView(show)
103
103
  }
104
-
104
+
105
+
106
+
107
+ Prop<Double?>("androidStatusBarPaddingTop") { view, topDp ->
108
+ view.applyAndroidStatusBarPaddingTop(topDp)
109
+ }
110
+
111
+ Prop<Boolean>("showCamera") { view, enabled ->
112
+ view.applyShowCamera(enabled)
113
+ }
114
+
115
+ Prop<Boolean>("showUIElements") { view, visible ->
116
+ view.applyShowUIElements(visible)
117
+ }
118
+
119
+ Prop<Boolean>("showTrafficBar") { view, enabled ->
120
+ view.applyAndroidTrafficBarEnabled(enabled)
121
+ }
122
+
123
+ Prop<Boolean>("showTrafficButton"){ view, enabled ->
124
+ view.applyShowTrafficButton(enabled)
125
+ }
126
+
127
+ Prop<Boolean>("showBrowseRouteButton") { view, enabled ->
128
+ view.applyShowBrowseRouteButton(enabled)
129
+ }
130
+
131
+ Prop<Boolean>("showVectorline"){ view, enabled ->
132
+ view.applyShowVectorline(enabled)
133
+ }
134
+
135
+ Prop<Boolean>("showGreyAfterPass") { view, enabled ->
136
+ view.applyShowGreyAfterPass(enabled)
137
+ }
138
+
105
139
  // 方法
106
140
  AsyncFunction("startNavigation") { view: ExpoGaodeMapNaviView, startLat: Double, startLng: Double, endLat: Double, endLng: Double, promise: expo.modules.kotlin.Promise ->
107
141
  view.startNavigation(startLat, startLng, endLat, endLng, promise)
@@ -112,4 +146,4 @@ class ExpoGaodeMapNaviViewModule : Module() {
112
146
  }
113
147
  }
114
148
  }
115
- }
149
+ }
@@ -1,5 +1,6 @@
1
1
  package expo.modules.gaodemap.navigation
2
2
 
3
+ import android.annotation.SuppressLint
3
4
  import android.content.Context
4
5
  import com.amap.api.navi.AMapNavi
5
6
  import com.amap.api.navi.model.AMapCarInfo
@@ -43,6 +44,7 @@ class ExpoGaodeMapNavigationModule : Module() {
43
44
  private val independentRouteManager = IndependentRouteManager()
44
45
  private var independentRouteService: IndependentRouteService? = null
45
46
 
47
+ @SuppressLint("SuspiciousIndentation")
46
48
  override fun definition() = ModuleDefinition {
47
49
  Name("ExpoGaodeMapNavigation")
48
50
 
@@ -1,9 +1,7 @@
1
1
  export * from './ExpoGaodeMap.types';
2
- export * from './types';
3
2
  export { default as ExpoGaodeMapModule, getWebKey, getSDKConfig } from './ExpoGaodeMapModule';
4
3
  export type { SDKConfig, PermissionStatus } from './ExpoGaodeMapModule';
5
4
  export { default as MapView } from './ExpoGaodeMapView';
6
- export type { MapViewRef } from './ExpoGaodeMapView';
7
5
  export { Marker, Polyline, Polygon, Circle, HeatMap, MultiPoint, Cluster, } from './components/overlays';
8
6
  export { requireModule, OptionalModules, getInstalledModules, printModuleInfo, createLazyLoader, } from './utils/ModuleLoader';
9
7
  export { default } from './ExpoGaodeMapModule';
@@ -20,7 +20,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
20
20
  exports.default = exports.createLazyLoader = exports.printModuleInfo = exports.getInstalledModules = exports.OptionalModules = exports.requireModule = exports.Cluster = exports.MultiPoint = exports.HeatMap = exports.Circle = exports.Polygon = exports.Polyline = exports.Marker = exports.MapView = exports.getSDKConfig = exports.getWebKey = exports.ExpoGaodeMapModule = void 0;
21
21
  // 导出类型定义
22
22
  __exportStar(require("./ExpoGaodeMap.types"), exports);
23
- __exportStar(require("./types"), exports);
24
23
  // 导出原生模块 - 直接使用,无需封装
25
24
  var ExpoGaodeMapModule_1 = require("./ExpoGaodeMapModule");
26
25
  Object.defineProperty(exports, "ExpoGaodeMapModule", { enumerable: true, get: function () { return __importDefault(ExpoGaodeMapModule_1).default; } });
@@ -152,26 +152,25 @@ export interface NaviViewProps extends ViewProps {
152
152
  */
153
153
  showTrafficLightView?: boolean;
154
154
  /**
155
- * 是否显示路线
156
- * @platform ios
157
- * @default true
155
+ * 导航界面顶部与状态栏的间距(单位:dp)
156
+ * @platform android
157
+ * @default 状态栏高度(单位:dp)
158
158
  */
159
- showRoute?: boolean;
159
+ androidStatusBarPaddingTop?: number;
160
160
  /**
161
- * 是否显示转向箭头
161
+ * 是否显示路线
162
162
  * @platform ios
163
163
  * @default true
164
164
  */
165
- showTurnArrow?: boolean;
165
+ showRoute?: boolean;
166
166
  /**
167
167
  * 是否显示路况光柱
168
- * @platform ios
169
168
  * @default true
170
169
  */
171
170
  showTrafficBar?: boolean;
172
171
  /**
173
172
  * 是否显示全览按钮
174
- * @platform ios
173
+ *
175
174
  * @default true
176
175
  */
177
176
  showBrowseRouteButton?: boolean;
@@ -183,25 +182,25 @@ export interface NaviViewProps extends ViewProps {
183
182
  showMoreButton?: boolean;
184
183
  /**
185
184
  * 是否显示实时交通按钮
186
- * @platform ios
185
+ *
187
186
  * @default true
188
187
  */
189
188
  showTrafficButton?: boolean;
190
189
  /**
191
190
  * 是否显示界面元素(设为false可完全自定义界面)
192
- * @platform ios
191
+ * 提示:ios 暂时无效,android 有效
193
192
  * @default true
194
193
  */
195
194
  showUIElements?: boolean;
196
195
  /**
197
196
  * 走过的路线是否置灰
198
- * @platform ios
197
+ *
199
198
  * @default false
200
199
  */
201
200
  showGreyAfterPass?: boolean;
202
201
  /**
203
202
  * 是否显示牵引线(起点到终点的飞线)
204
- * @platform ios
203
+ *
205
204
  * @default true
206
205
  */
207
206
  showVectorline?: boolean;
@@ -5,6 +5,7 @@
5
5
  //
6
6
  //
7
7
 
8
+ import Foundation
8
9
  import ExpoModulesCore
9
10
  import AMapNaviKit
10
11
 
@@ -84,6 +85,11 @@ public class ExpoGaodeMapNaviView: ExpoView {
84
85
 
85
86
  // MARK: - Properties
86
87
  private var driveView: AMapNaviDriveView?
88
+ private var driveViewLoaded: Bool = false
89
+ private var pendingShowUIElements: Bool?
90
+ private var pendingShowUIElementsWorkItem: DispatchWorkItem?
91
+ private var hasStartedNavi: Bool = false
92
+ private var hasReceivedFirstNaviData: Bool = false
87
93
  private var driveManager: AMapNaviDriveManager?
88
94
 
89
95
  // Props - 通用属性
@@ -136,7 +142,7 @@ public class ExpoGaodeMapNaviView: ExpoView {
136
142
  didSet { driveView?.showTrafficButton = showTrafficButton }
137
143
  }
138
144
  var showUIElements: Bool = true {
139
- didSet { driveView?.showUIElements = showUIElements }
145
+ didSet { applyShowUIElementsToDriveViewIfReady() }
140
146
  }
141
147
  var showGreyAfterPass: Bool = false {
142
148
  didSet { driveView?.showGreyAfterPass = showGreyAfterPass }
@@ -153,6 +159,10 @@ public class ExpoGaodeMapNaviView: ExpoView {
153
159
  var lineWidth: CGFloat = 0 {
154
160
  didSet { driveView?.lineWidth = lineWidth }
155
161
  }
162
+
163
+ func applyShowUIElements(_ visible: Bool) {
164
+ showUIElements = visible
165
+ }
156
166
 
157
167
  // 坐标
158
168
  private var startCoordinate: AMapNaviPoint?
@@ -222,15 +232,68 @@ public class ExpoGaodeMapNaviView: ExpoView {
222
232
  driveView?.showBrowseRouteButton = showBrowseRouteButton
223
233
  driveView?.showMoreButton = showMoreButton
224
234
  driveView?.showTrafficButton = showTrafficButton
225
- driveView?.showUIElements = showUIElements
226
235
  driveView?.showGreyAfterPass = showGreyAfterPass
227
236
  driveView?.showVectorline = showVectorline
228
237
  driveView?.showTrafficLights = showTrafficLights
229
238
  if lineWidth > 0 {
230
239
  driveView?.lineWidth = lineWidth
231
240
  }
241
+
242
+ applyShowUIElementsToDriveViewIfReady()
232
243
  }
233
-
244
+
245
+ private func applyShowUIElementsToDriveViewIfReady() {
246
+ guard driveView != nil else {
247
+ pendingShowUIElements = showUIElements
248
+ return
249
+ }
250
+
251
+ guard driveViewLoaded else {
252
+ pendingShowUIElements = showUIElements
253
+ return
254
+ }
255
+
256
+ let value = pendingShowUIElements ?? showUIElements
257
+ pendingShowUIElements = nil
258
+
259
+ if value == false && (!hasStartedNavi || !hasReceivedFirstNaviData) {
260
+ pendingShowUIElements = false
261
+ pendingShowUIElementsWorkItem?.cancel()
262
+ let workItem = DispatchWorkItem { [weak self] in
263
+ guard let self else { return }
264
+ self.applyDriveViewShowUIElements(true, remainingAttempts: 20)
265
+ }
266
+ pendingShowUIElementsWorkItem = workItem
267
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.08, execute: workItem)
268
+ return
269
+ }
270
+
271
+ pendingShowUIElementsWorkItem?.cancel()
272
+ let workItem = DispatchWorkItem { [weak self] in
273
+ guard let self else { return }
274
+ self.applyDriveViewShowUIElements(value, remainingAttempts: 20)
275
+ }
276
+ pendingShowUIElementsWorkItem = workItem
277
+
278
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.08, execute: workItem)
279
+ }
280
+
281
+ private func applyDriveViewShowUIElements(_ value: Bool, remainingAttempts: Int) {
282
+ guard let driveView else { return }
283
+
284
+ if driveView.bounds.isEmpty {
285
+ if remainingAttempts <= 0 {
286
+ return
287
+ }
288
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.05) { [weak self] in
289
+ self?.applyDriveViewShowUIElements(value, remainingAttempts: remainingAttempts - 1)
290
+ }
291
+ return
292
+ }
293
+
294
+ driveView.showUIElements = value
295
+ }
296
+
234
297
  // MARK: - Prop Setters
235
298
  private func applyShowCamera(_ show: Bool) {
236
299
  driveView?.showCamera = show
@@ -366,6 +429,7 @@ public class ExpoGaodeMapNaviView: ExpoView {
366
429
  extension ExpoGaodeMapNaviView: AMapNaviDriveManagerDelegate {
367
430
 
368
431
  public func driveManager(onCalculateRouteSuccess driveManager: AMapNaviDriveManager) {
432
+ hasStartedNavi = true
369
433
  onRouteCalculated([
370
434
  "success": true,
371
435
  "naviType": naviType
@@ -377,6 +441,8 @@ extension ExpoGaodeMapNaviView: AMapNaviDriveManagerDelegate {
377
441
  } else {
378
442
  driveManager.startGPSNavi()
379
443
  }
444
+
445
+ applyShowUIElementsToDriveViewIfReady()
380
446
  }
381
447
 
382
448
  public func driveManager(_ driveManager: AMapNaviDriveManager, onCalculateRouteFailure error: Error) {
@@ -387,10 +453,13 @@ extension ExpoGaodeMapNaviView: AMapNaviDriveManagerDelegate {
387
453
  }
388
454
 
389
455
  public func driveManager(_ driveManager: AMapNaviDriveManager, didStartNavi naviMode: AMapNaviMode) {
456
+ hasStartedNavi = true
390
457
  onNavigationStarted([
391
458
  "type": naviMode == .emulator ? 1 : 0,
392
459
  "isEmulator": naviMode == .emulator
393
460
  ])
461
+
462
+ applyShowUIElementsToDriveViewIfReady()
394
463
  }
395
464
 
396
465
  public func driveManagerNavi(_ driveManager: AMapNaviDriveManager, didArrive wayPoint: AMapNaviPoint) {
@@ -404,6 +473,10 @@ extension ExpoGaodeMapNaviView: AMapNaviDriveManagerDelegate {
404
473
  }
405
474
 
406
475
  public func driveManager(_ driveManager: AMapNaviDriveManager, didUpdate naviLocation: AMapNaviLocation) {
476
+ if !hasReceivedFirstNaviData {
477
+ hasReceivedFirstNaviData = true
478
+ applyShowUIElementsToDriveViewIfReady()
479
+ }
407
480
  onLocationUpdate([
408
481
  "latitude": naviLocation.coordinate.latitude,
409
482
  "longitude": naviLocation.coordinate.longitude,
@@ -413,6 +486,10 @@ extension ExpoGaodeMapNaviView: AMapNaviDriveManagerDelegate {
413
486
  }
414
487
 
415
488
  public func driveManager(_ driveManager: AMapNaviDriveManager, didUpdate naviInfo: AMapNaviInfo) {
489
+ if !hasReceivedFirstNaviData {
490
+ hasReceivedFirstNaviData = true
491
+ applyShowUIElementsToDriveViewIfReady()
492
+ }
416
493
  onNavigationInfoUpdate([
417
494
  "currentRoadName": naviInfo.currentRoadName ?? "",
418
495
  "nextRoadName": naviInfo.nextRoadName ?? "",
@@ -458,6 +535,13 @@ extension ExpoGaodeMapNaviView: AMapNaviDriveManagerDelegate {
458
535
  extension ExpoGaodeMapNaviView: AMapNaviDriveViewDelegate {
459
536
 
460
537
  public func driveViewDidLoad(_ driveView: AMapNaviDriveView) {
538
+ driveViewLoaded = true
539
+ applyViewOptions()
540
+ applyShowUIElementsToDriveViewIfReady()
461
541
  onNavigationReady([:])
462
542
  }
543
+
544
+ public func driveViewEdgePadding(_ driveView: AMapNaviDriveView) -> UIEdgeInsets {
545
+ return .zero
546
+ }
463
547
  }
@@ -76,7 +76,7 @@ public class ExpoGaodeMapNaviViewModule: Module {
76
76
  view.showRoute = value
77
77
  }
78
78
 
79
- Prop("showTurnArrow") { (view: ExpoGaodeMapNaviView, value: Bool) in
79
+ Prop("naviArrowVisible") { (view: ExpoGaodeMapNaviView, value: Bool) in
80
80
  view.showTurnArrow = value
81
81
  }
82
82
 
@@ -97,7 +97,7 @@ public class ExpoGaodeMapNaviViewModule: Module {
97
97
  }
98
98
 
99
99
  Prop("showUIElements") { (view: ExpoGaodeMapNaviView, value: Bool) in
100
- view.showUIElements = value
100
+ view.applyShowUIElements(value)
101
101
  }
102
102
 
103
103
  Prop("showGreyAfterPass") { (view: ExpoGaodeMapNaviView, value: Bool) in
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-gaode-map-navigation",
3
- "version": "1.1.2-next.0",
3
+ "version": "1.1.2-next.1",
4
4
  "description": "高德地图导航功能模块 - 路径规划、导航引导,独立版本包含完整地图功能",
5
5
  "author": "<TomWq> (https://github.com/TomWq)",
6
6
  "repository": "https://github.com/TomWq/expo-gaode-map",