다중 경유지 길찾기 관련해서 질문있습니다

package com.example.easytrip

import android.app.Activity
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Color
import android.os.Bundle
import android.util.Base64
import android.util.Log
import android.view.View
import android.view.ViewGroup
import com.kakao.vectormap.KakaoMap
import com.kakao.vectormap.KakaoMapReadyCallback
import com.kakao.vectormap.KakaoMapSdk
import com.kakao.vectormap.LatLng
import com.kakao.vectormap.MapLifeCycleCallback
import com.kakao.vectormap.MapOverlay
import com.kakao.vectormap.MapView
import com.kakao.vectormap.camera.CameraUpdateFactory
import com.kakao.vectormap.label.Label
import com.kakao.vectormap.label.LabelLayer
import com.kakao.vectormap.label.LabelOptions
import com.kakao.vectormap.label.LabelStyle
import com.kakao.vectormap.label.LabelTextBuilder
import com.kakao.vectormap.route.RouteLineOptions
import com.kakao.vectormap.route.RouteLineSegment
import com.kakao.vectormap.route.RouteLineStyle
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.StandardMessageCodec
import io.flutter.plugin.platform.PlatformView
import io.flutter.plugin.platform.PlatformViewFactory
import okhttp3.OkHttpClient
import okhttp3.Request
import org.json.JSONObject
import java.io.IOException
import java.net.URLEncoder
import java.security.MessageDigest

class MainActivity : FlutterActivity() {

  var mapView: MapView? = null
  lateinit var kakaoMap: KakaoMap
  var isMapReady = false  // 지도가 준비되었는지 여부를 저장
  private lateinit var labelLayer: LabelLayer  // LabelLayer 추가
  private val labels = mutableListOf<Label>()  // Label 리스트
  private val labelOptionsList = mutableListOf<LabelOptions>()  // LabelOptions 리스트
  private var startAddLabel: Label? = null
  private var endAddLabel: Label? = null
  private val CHANNEL = "com.example.easytrip/map"

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    // KakaoMapSdk 초기화
    KakaoMapSdk.init(this, "5d2bc59246a7ef930e925c3535a64fb7")

    // MapView 초기화
    initializeMapView()

    // 지도 관련 MethodChannel
    MethodChannel(flutterEngine!!.dartExecutor.binaryMessenger, "com.example.easytrip/map")
      .setMethodCallHandler { call, result ->
        when (call.method) {
          "zoomIn" -> {
            if (isMapReady) {
              kakaoMap.moveCamera(CameraUpdateFactory.zoomIn())
              result.success(null)
            } else {
              result.error("MAP_NOT_READY", "Map is not ready", null)
            }
          }
          "zoomOut" -> {
            if (isMapReady) {
              kakaoMap.moveCamera(CameraUpdateFactory.zoomOut())
              result.success(null)
            } else {
              result.error("MAP_NOT_READY", "Map is not ready", null)
            }
          }
          "moveToLocation" -> {
            val latitude = (call.arguments as Map<*, *>?)?.get("latitude") as? Double
            val longitude = (call.arguments as Map<*, *>?)?.get("longitude") as? Double
            if (latitude != null && longitude != null) {
              if (isMapReady) {
                moveToLocation(latitude, longitude)
                result.success(null)
              } else {
                result.error("MAP_NOT_READY", "Map is not ready", null)
              }
            } else {
              result.error("INVALID_ARGUMENTS", "Invalid coordinates", null)
            }
          }
          "addLabel" -> {
            val latitude = (call.arguments as Map<*, *>?)?.get("latitude") as? Double
            val longitude = (call.arguments as Map<*, *>?)?.get("longitude") as? Double
            val isStartPoint = (call.arguments as Map<*, *>?)?.get("isStartPoint") as? Boolean
            if (latitude != null && longitude != null) {
              if (isStartPoint != null) {
                addLabel(latitude, longitude, isStartPoint)
              } else {
                addLabel(latitude, longitude)
              }
            }
            result.success(null)
          }
          "removeMapView" -> {
            removeMapView()
            result.success(null)
          }
          "removeLabel" -> {
            startAddLabel?.let { removeLabel(it) }
            endAddLabel?.let { removeLabel(it) }
            result.success(null)
          }
          "setBicycleOverlay" -> {
            if (isMapReady) {
              setBicycleOverlay()
              result.success(null)
            } else {
              result.error("MAP_NOT_READY", "Map is not ready", null)
            }
          }
          "setRoadViewLineOverlay" -> {

            if (isMapReady) {
              setRoadViewLineOverlay()
              result.success(null)
            } else {
              result.error("INVALID_ARGUMENTS", "Invalid coordinates", null)
            }
          }
          "drawRouteLine" -> {
            val startLatLng = call.arguments as Map<String, Double>
            val startLatitude = startLatLng["startLatitude"] ?: 0.0
            val startLongitude = startLatLng["startLongitude"] ?: 0.0
            val endLatitude = startLatLng["endLatitude"] ?: 0.0
            val endLongitude = startLatLng["endLongitude"] ?: 0.0
            if (startLatitude != 0.0 && startLongitude != 0.0 && endLatitude != 0.0 && endLongitude != 0.0) {
              drawRouteLine(startLatitude, startLongitude, endLatitude, endLongitude)
              result.success(null)
            } else {
              result.error("INVALID_COORDINATES", "Invalid coordinates for route", null)
            }
          }
          "getCarRoute" -> {
            val startLat = call.argument<Double>("startLatitude") ?: 0.0
            val startLng = call.argument<Double>("startLongitude") ?: 0.0
            val endLat = call.argument<Double>("endLatitude") ?: 0.0
            val endLng = call.argument<Double>("endLongitude") ?: 0.0
            val waypoints: List<Map<String, Double>> = call.argument("waypoints") ?: emptyList()  // 경유지 리스트 전달
            fetchCarRoute(startLat, startLng, endLat, endLng, waypoints)
            result.success(null)
          }
          "getWalkingRoute" -> {
            val startLat = call.argument<Double>("startLatitude") ?: 0.0
            val startLng = call.argument<Double>("startLongitude") ?: 0.0
            val endLat = call.argument<Double>("endLatitude") ?: 0.0
            val endLng = call.argument<Double>("endLongitude") ?: 0.0
            val waypoints: List<Map<String, Double>> = call.argument("waypoints") ?: emptyList()  // 경유지 리스트 전달
            fetchWalkingRoute(startLat, startLng, endLat, endLng, waypoints)
            result.success(null)
          }
          "getBicycleRoute" -> {
            val startLat = call.argument<Double>("startLatitude") ?: 0.0
            val startLng = call.argument<Double>("startLongitude") ?: 0.0
            val endLat = call.argument<Double>("endLatitude") ?: 0.0
            val endLng = call.argument<Double>("endLongitude") ?: 0.0
            val waypoints: List<Map<String, Double>> = call.argument("waypoints") ?: emptyList()  // 경유지 리스트 전달
            fetchBicycleRoute(startLat, startLng, endLat, endLng, waypoints)
            result.success(null)
          }
          "addLabel" -> {
            val latitude = (call.arguments as Map<*, *>?)?.get("latitude") as? Double
            val longitude = (call.arguments as Map<*, *>?)?.get("longitude") as? Double
            val isStartPoint = (call.arguments as Map<*, *>?)?.get("isStartPoint") as? Boolean
            val isWaypoint = (call.arguments as Map<*, *>?)?.get("isWaypoint") as? Boolean  // 경유지 여부

            if (latitude != null && longitude != null) {
              when {
                isStartPoint == true -> {
                  addLabel(latitude, longitude, true)  // 출발지 라벨 추가
                }
                isWaypoint == true -> {
                  addWaypointLabel(latitude, longitude)  // 경유지 라벨 추가
                }
                else -> {
                  addLabel(latitude, longitude)  // 도착지 또는 일반 라벨 추가
                }
              }
            }
            result.success(null)
          }

          "drawRouteWithWaypoints" -> {
            val startLat = call.argument<Double>("startLatitude") ?: 0.0
            val startLng = call.argument<Double>("startLongitude") ?: 0.0
            val endLat = call.argument<Double>("endLatitude") ?: 0.0
            val endLng = call.argument<Double>("endLongitude") ?: 0.0
            val waypoints = call.argument<List<Map<String, Double>>>("waypoints") ?: emptyList()

            drawRouteLineWithWaypoints(startLat, startLng, endLat, endLng, waypoints)
            result.success(null)
          }
          else -> result.notImplemented()
        }
      }

    // 검색 관련 MethodChannel 추가
    MethodChannel(flutterEngine!!.dartExecutor.binaryMessenger, "com.example.easytrip/search")
      .setMethodCallHandler { call, result ->
        when (call.method) {
          "search" -> {
            val keyword = call.arguments as String
            searchPlaces(keyword, result)
          }
          else -> result.notImplemented()
        }
      }
  }

  // 자전거 도로 오버레이 활성화
  private fun setBicycleOverlay() {
    if (isMapReady) {
      // 1. MapOverlay를 사용하여 자전거 도로 오버레이 설정
      kakaoMap.showOverlay(MapOverlay.BICYCLE_ROAD)
      Log.d("KakaoMap", "Bicycle overlay enabled")
    } else {
      Log.e("KakaoMap", "BICYCLE_ROAD KakaoMap is not initialized")
    }
  }

  // 로드뷰 오버레이 활성화
  private fun setRoadViewLineOverlay() {
    if (isMapReady) {
      kakaoMap.showOverlay(MapOverlay.ROADVIEW_LINE)
      Log.d("KakaoMap", "Road view line overlay enabled")
    } else {
      Log.e("KakaoMap", "KakaoMap is not initialized")
    }
  }

  private fun removeMapView() {
    if (mapView != null) {
      val parent = mapView!!.parent as? ViewGroup
      parent?.removeView(mapView)
      mapView = null
    }
  }

  override fun onDestroy() {
    super.onDestroy()
    mapView = null
  }

  private fun initializeMapView() {
    mapView = MapView(this)
    mapView?.start(object : MapLifeCycleCallback() {
      override fun onMapDestroy() {
        Log.d("KakaoMap", "Map destroyed")
      }

      override fun onMapError(error: Exception) {
        Log.e("KakaoMap", "Map error: ${error.message}")
      }
    }, object : KakaoMapReadyCallback() {
      override fun onMapReady(map: KakaoMap) {
        kakaoMap = map
        isMapReady = true  // 지도 준비 완료 플래그 설정

        labelLayer = kakaoMap.labelManager?.getLayer() ?: run {
          Log.e("KakaoMap", "LabelLayer is not initialized")
          return
        }  // LabelLayer 초기화

        Log.d("KakaoMap", "KakaoMap is ready")
        moveToLocation(37.5665, 126.9780)
      }
    })
  }

  private fun moveToLocation(latitude: Double, longitude: Double) {
    if (isMapReady) {
      val position = LatLng.from(latitude, longitude)
      val cameraUpdate = CameraUpdateFactory.newCenterPosition(position)
      kakaoMap.moveCamera(cameraUpdate)
    } else {
      Log.e("KakaoMap", "KakaoMap is not initialized")
    }
  }

  // LabelLayer가 초기화되어 있지 않으면 초기화하는 메서드
  private fun initializeLabelLayerIfNeeded() {
    if (!::labelLayer.isInitialized && isMapReady) {
      labelLayer = kakaoMap.labelManager?.getLayer() ?: run {
        Log.e("KakaoMap", "Failed to initialize LabelLayer")
        return
      }
      Log.d("KakaoMap", "LabelLayer initialized")
    }
  }

  // 새로운 Label 추가
  private fun addLabel(latitude: Double, longitude: Double) {
    initializeLabelLayerIfNeeded() // labelLayer 초기화 확인

    if (isMapReady) {
      Log.d("KakaoMap", "Adding label at: $latitude, $longitude")
      val pos = LatLng.from(latitude, longitude)

      // BitmapFactory를 사용해 drawable을 비트맵으로 변환
      val bitmap = BitmapFactory.decodeResource(resources, R.drawable.custom_marker)
      val scaledBitmap = Bitmap.createScaledBitmap(bitmap, 100, 100, true)

      // LabelOptions 생성
      val labelOptions = LabelOptions.from(pos).setStyles(LabelStyle.from(scaledBitmap))

      // 레이블 추가하고 LabelOptions 저장
      labelLayer.addLabel(labelOptions)
      labelOptionsList.add(labelOptions)

      Log.d("KakaoMap", "Label added at: $latitude, $longitude")
    } else {
      Log.e("KakaoMap", "KakaoMap is not initialized")
    }
  }

  fun addLabel(latitude: Double, longitude: Double, isStartPoint: Boolean) {
    initializeLabelLayerIfNeeded() // labelLayer 초기화 확인

    if (!::labelLayer.isInitialized) {
      Log.e("KakaoMap", "LabelLayer is not initialized")
      return
    }

    // 좌표 설정
    val pos = LatLng.from(latitude, longitude)

    // "출발지"와 "도착지"에 맞는 비트맵 설정
    val bitmapResource = if (isStartPoint) R.drawable.start_marker else R.drawable.end_marker
    val bitmap = BitmapFactory.decodeResource(resources, bitmapResource)
    val resizedBitmap = Bitmap.createScaledBitmap(bitmap, 150, 150, false)

    // LabelTextBuilder를 사용하여 텍스트 설정
    val labelTextBuilder = LabelTextBuilder().setTexts(if (isStartPoint) "출발지" else "도착지")

    // LabelStyle 생성 및 텍스트 스타일 추가
    val labelStyle = LabelStyle.from(resizedBitmap).setTextStyles(20, Color.BLACK)

    // LabelOptions 생성
    val labelOptions = LabelOptions.from(pos)
      .setTexts(labelTextBuilder) // LabelTextBuilder를 사용하여 텍스트 설정
      .setStyles(labelStyle)

    // 이전 라벨 제거 후 새로운 라벨 추가 (출발지 또는 도착지)
    if (isStartPoint) {
      startAddLabel?.let { labelLayer.remove(it) }
      startAddLabel = labelLayer.addLabel(labelOptions)
    } else {
      endAddLabel?.let { labelLayer.remove(it) }
      endAddLabel = labelLayer.addLabel(labelOptions)
    }

    Log.d("KakaoMap", "Label added at: $latitude, $longitude")
  }

  // 모든 Label 삭제
  private fun removeLabel(label: Label) {
    if (isMapReady && ::labelLayer.isInitialized) {
      kakaoMap.labelManager?.clearAll()  // 특정 라벨만 제거할 수 없다면 레이어 전체를 초기화
      labels.remove(label)   // 리스트에서 해당 라벨 제거
      Log.d("KakaoMap", "Label removed: ${label.labelId}")
    } else {
      Log.e("KakaoMap", "KakaoMap or LabelLayer is not initialized")
    }
  }

  override fun onResume() {
    super.onResume()
    if (isMapReady) {
      // 복귀 시 이전에 추가된 레이블들을 다시 추가
      restoreLabels()
    }
  }

  // 모든 레이블을 복구하는 함수
  private fun restoreLabels() {
    for (labelOptions in labelOptionsList) {
      labelLayer.addLabel(labelOptions)  // 저장된 LabelOptions를 사용하여 레이블 복구
    }
    Log.d("KakaoMap", "All labels restored after onResume")
  }

  // 검색 기능 구현
  private fun searchPlaces(keyword: String, result: MethodChannel.Result) {
    val client = OkHttpClient()
    val url = "https://dapi.kakao.com/v2/local/search/keyword.json?query=${URLEncoder.encode(keyword, "UTF-8")}"
    val apiKey = "06458f1a2d01e02bb731d2a37cfa6c85"  // 여기에 본인의 REST API 키를 입력하세요
    val request = Request.Builder()
      .url(url)
      .addHeader("Authorization", "KakaoAK $apiKey")
      .build()

    Log.d("searchPlaces", "Request URL: $url")

    client.newCall(request).enqueue(object : okhttp3.Callback {
      override fun onFailure(call: okhttp3.Call, e: IOException) {
        runOnUiThread {
          Log.e("searchPlaces", "Request failed: ${e.message}")
          result.error("ERROR", e.message, null)
        }
      }

      override fun onResponse(call: okhttp3.Call, response: okhttp3.Response) {
        val responseData = response.body?.string()
        runOnUiThread {
          Log.d("searchPlaces", "Response code: ${response.code}")
          if (response.isSuccessful && responseData != null) {
            Log.d("searchPlaces", "Response successful: $responseData")
            result.success(responseData)
          } else {
            Log.e("searchPlaces", "Response failed: ${response.message}")
            result.error("ERROR", "Failed to get response", null)
          }
        }
      }
    })
  }

  private fun drawRouteLine(startLatitude: Double, startLongitude: Double, endLatitude: Double, endLongitude: Double) {
    if (isMapReady) {
      val startLatLng = LatLng.from(startLatitude, startLongitude)
      val endLatLng = LatLng.from(endLatitude, endLongitude)

      // 1. RouteLine 스타일 설정 (lineWidth: Float, lineColor: Int)
      val routeLineStyle = RouteLineStyle.from(16f, Color.BLUE)  // 두께 16, 파란색 경로 라인

      // 2. RouteLineSegment 생성
      val segment = RouteLineSegment.from(listOf(startLatLng, endLatLng)).setStyles(routeLineStyle)

      // 3. RouteLineOptions 생성 (segments: List<RouteLineSegment>)
      val routeLineOptions = RouteLineOptions.from(listOf(segment))

      // 4. RouteLineLayer 가져오기
      val layer = kakaoMap.getRouteLineManager()?.getLayer()

      // 5. RouteLine 추가
      val routeLine = layer?.addRouteLine(routeLineOptions)

      Log.d("KakaoMap", "Route line added from $startLatitude, $startLongitude to $endLatitude, $endLongitude")
    } else {
      Log.e("KakaoMap", "Map is not ready to draw route line")
    }
  }

  fun fetchWalkingRoute(
    startLatitude: Double,
    startLongitude: Double,
    endLatitude: Double,
    endLongitude: Double,
    waypoints: List<Map<String, Double>>  // waypoints 추가
  ) {
    val client = OkHttpClient()

    // 경유지를 처리하는 문자열 생성
    val waypointsString = waypoints.joinToString("|") { "${it["longitude"]},${it["latitude"]}" }

    val url = "https://apis-navi.kakaomobility.com/v1/waypoints/directions?origin=${startLongitude},${startLatitude}&waypoints=${waypointsString}&destination=${endLongitude},${endLatitude}&priority=RECOMMEND&roadDetails=false&vehicleType=1"

    val request = Request.Builder()
      .url(url)
      .addHeader("Authorization", "KakaoAK 06458f1a2d01e02bb731d2a37cfa6c85")  // REST API 키 입력
      .build()

    client.newCall(request).enqueue(object : okhttp3.Callback {
      override fun onFailure(call: okhttp3.Call, e: IOException) {
        runOnUiThread {
          Log.e("RouteLine", "Failed to get route: ${e.message}")
        }
      }

      override fun onResponse(call: okhttp3.Call, response: okhttp3.Response) {
        // 여기서 응답 본문을 사용하고 닫아야 함
        response.use {  // 응답 본문을 처리한 후 자동으로 close()됨
          if (!response.isSuccessful) {
            Log.e("RouteLine", "Failed to get route: ${response.message}")
            return
          }

          val responseData = response.body?.string()
          Log.d("RouteLine", "Response Data: $responseData")

          val jsonResponse = JSONObject(responseData)
          val routes = jsonResponse.getJSONArray("routes")
          if (routes.length() == 0) {
            Log.e("RouteLine", "No routes found in the response")
            return
          }

          // 경로 데이터에서 vertexes를 추출
          val routePoints = routes.getJSONObject(0).getJSONArray("sections").getJSONObject(0).getJSONArray("roads")

          // 경로 점들을 담을 리스트 생성
          val points = mutableListOf<LatLng>()
          for (i in 0 until routePoints.length()) {
            val road = routePoints.getJSONObject(i)
            val vertexes = road.getJSONArray("vertexes")

            // vertexes 배열은 [lng1, lat1, lng2, lat2, ...] 형식으로 구성됨
            for (j in 0 until vertexes.length() step 2) {
              val lng = vertexes.getDouble(j)
              val lat = vertexes.getDouble(j + 1)
              points.add(LatLng.from(lat, lng))
            }
          }

          runOnUiThread {
            if (points.isNotEmpty()) {
              // RouteLineSegment 생성
              val routeLineStyle = RouteLineStyle.from(10f, Color.BLUE)
              val segment = RouteLineSegment.from(points).setStyles(routeLineStyle)

              // RouteLineOptions 생성
              val routeLineOptions = RouteLineOptions.from(listOf(segment))

              // RouteLineLayer에 경로 추가
              val layer = kakaoMap.getRouteLineManager()?.getLayer()
              layer?.addRouteLine(routeLineOptions)

              // 경로가 잘 보이도록 카메라 이동
              moveToFitRoute(points.toTypedArray())  // 경로 전체를 화면에 맞춤
            } else {
              Log.e("RouteLine", "Not enough points to draw a route")
            }
          }
        } // response.use 끝, 응답이 닫힘
      }
    })
  }

  fun fetchCarRoute(
    startLatitude: Double,
    startLongitude: Double,
    endLatitude: Double,
    endLongitude: Double,
    waypoints: List<Map<String, Double>>  // 경유지 추가
  ) {
    val client = OkHttpClient()

    // 경유지 유무에 따라 다른 URL을 사용
    val url: String
    if (waypoints.isNotEmpty()) {
      // 경유지가 있을 때
      val waypointsString = waypoints.joinToString("|") { "${it["longitude"]},${it["latitude"]}" }
      Log.d("RouteLine", "Waypoints present. Waypoints String: $waypointsString")
      url = "https://apis-navi.kakaomobility.com/v1/waypoints/directions?origin=${startLongitude},${startLatitude}&waypoints=${waypointsString}&destination=${endLongitude},${endLatitude}&priority=RECOMMEND&roadDetails=false&vehicleType=2"
    } else {
      // 경유지가 없을 때
      Log.d("RouteLine", "No waypoints present.")
      url = "https://apis-navi.kakaomobility.com/v1/directions?origin=${startLongitude},${startLatitude}&destination=${endLongitude},${endLatitude}&priority=RECOMMEND&roadDetails=false&vehicleType=2"
    }

    Log.d("RouteLine", "Request URL: $url")

    val request = Request.Builder()
      .url(url)
      .addHeader("Authorization", "KakaoAK 06458f1a2d01e02bb731d2a37cfa6c85")  // REST API 키 입력
      .build()

    client.newCall(request).enqueue(object : okhttp3.Callback {
      override fun onFailure(call: okhttp3.Call, e: IOException) {
        runOnUiThread {
          Log.e("RouteLine", "Failed to get route: ${e.message}")
        }
      }

      override fun onResponse(call: okhttp3.Call, response: okhttp3.Response) {
        // 응답 본문을 처리하고 닫음
        response.use {
          if (!response.isSuccessful) {
            Log.e("RouteLine", "Failed to get route: ${response.message}")
            return
          }

          val responseData = response.body?.string()
          Log.d("RouteLine", "Response Data: $responseData")  // 응답 데이터를 확인하는 로그

          // 응답 데이터 파싱
          val jsonResponse = JSONObject(responseData)
          val routes = jsonResponse.optJSONArray("routes")

          if (routes == null || routes.length() == 0) {
            Log.e("RouteLine", "No routes found in the response")
            return
          }

          val sections = routes.getJSONObject(0).optJSONArray("sections")
          if (sections == null || sections.length() == 0) {
            Log.e("RouteLine", "No sections found in the route")
            return
          }

          val routePoints = sections.getJSONObject(0).getJSONArray("roads")
          Log.d("RouteLine", "Route points: $routePoints")  // 경로 포인트 확인

          val points = mutableListOf<LatLng>()
          for (i in 0 until routePoints.length()) {
            val road = routePoints.getJSONObject(i)
            val vertexes = road.getJSONArray("vertexes")
            Log.d("RouteLine", "Vertexes: $vertexes")  // 각 경로 지점의 좌표 로그
            for (j in 0 until vertexes.length() step 2) {
              val lng = vertexes.getDouble(j)
              val lat = vertexes.getDouble(j + 1)
              points.add(LatLng.from(lat, lng))
            }
          }

          Log.d("RouteLine", "Final route points: $points")

          runOnUiThread {
            if (points.isNotEmpty()) {
              val routeLineStyle = RouteLineStyle.from(10f, Color.BLUE)
              val segment = RouteLineSegment.from(points).setStyles(routeLineStyle)

              val routeLineOptions = RouteLineOptions.from(listOf(segment))
              val layer = kakaoMap.getRouteLineManager()?.getLayer()

              layer?.addRouteLine(routeLineOptions)

              Log.d("RouteLine", "Route line drawn successfully")
              moveToFitRoute(points.toTypedArray())  // 경로에 맞게 카메라 이동
            } else {
              Log.e("RouteLine", "Not enough points to draw a route")
            }
          }
        }
      }
    })
  }


  fun fetchBicycleRoute(
    startLatitude: Double,
    startLongitude: Double,
    endLatitude: Double,
    endLongitude: Double,
    waypoints: List<Map<String, Double>>  // waypoints 추가
  ) {
    val client = OkHttpClient()

    // 경유지를 처리하는 문자열 생성
    val waypointsString = waypoints.joinToString("|") { "${it["longitude"]},${it["latitude"]}" }

    val url = "https://apis-navi.kakaomobility.com/v1/waypoints/directions?origin=${startLongitude},${startLatitude}&waypoints=${waypointsString}&destination=${endLongitude},${endLatitude}&priority=RECOMMEND&roadDetails=false&vehicleType=3"

    val request = Request.Builder()
      .url(url)
      .addHeader("Authorization", "KakaoAK 06458f1a2d01e02bb731d2a37cfa6c85")  // REST API 키 입력
      .build()

    client.newCall(request).enqueue(object : okhttp3.Callback {
      override fun onFailure(call: okhttp3.Call, e: IOException) {
        runOnUiThread {
          Log.e("RouteLine", "Failed to get route: ${e.message}")
        }
      }

      override fun onResponse(call: okhttp3.Call, response: okhttp3.Response) {
        // 여기서 응답 본문을 사용하고 닫아야 함
        response.use {  // 응답 본문을 처리한 후 자동으로 close()됨
          if (!response.isSuccessful) {
            Log.e("RouteLine", "Failed to get route: ${response.message}")
            return
          }

          val responseData = response.body?.string()
          Log.d("RouteLine", "Response Data: $responseData")

          val jsonResponse = JSONObject(responseData)
          val routes = jsonResponse.getJSONArray("routes")
          if (routes.length() == 0) {
            Log.e("RouteLine", "No routes found in the response")
            return
          }

          // 경로 데이터에서 vertexes를 추출
          val routePoints = routes.getJSONObject(0).getJSONArray("sections").getJSONObject(0).getJSONArray("roads")

          // 경로 점들을 담을 리스트 생성
          val points = mutableListOf<LatLng>()
          for (i in 0 until routePoints.length()) {
            val road = routePoints.getJSONObject(i)
            val vertexes = road.getJSONArray("vertexes")

            // vertexes 배열은 [lng1, lat1, lng2, lat2, ...] 형식으로 구성됨
            for (j in 0 until vertexes.length() step 2) {
              val lng = vertexes.getDouble(j)
              val lat = vertexes.getDouble(j + 1)
              points.add(LatLng.from(lat, lng))
            }
          }

          runOnUiThread {
            if (points.isNotEmpty()) {
              // RouteLineSegment 생성
              val routeLineStyle = RouteLineStyle.from(10f, Color.BLUE)
              val segment = RouteLineSegment.from(points).setStyles(routeLineStyle)

              // RouteLineOptions 생성
              val routeLineOptions = RouteLineOptions.from(listOf(segment))

              // RouteLineLayer에 경로 추가
              val layer = kakaoMap.getRouteLineManager()?.getLayer()
              layer?.addRouteLine(routeLineOptions)

              // 경로가 잘 보이도록 카메라 이동
              moveToFitRoute(points.toTypedArray())  // 경로 전체를 화면에 맞춤
            } else {
              Log.e("RouteLine", "Not enough points to draw a route")
            }
          }
        } // response.use 끝, 응답이 닫힘
      }
    })
  }


  fun addWaypointLabel(latitude: Double, longitude: Double) {
    initializeLabelLayerIfNeeded() // labelLayer 초기화 확인

    if (isMapReady) {
      Log.d("KakaoMap", "Adding waypoint label at: $latitude, $longitude")
      val pos = LatLng.from(latitude, longitude)

      // BitmapFactory를 사용해 drawable을 비트맵으로 변환 (경유지 마커)
      val bitmap = BitmapFactory.decodeResource(resources, R.drawable.custom_marker)
      val scaledBitmap = Bitmap.createScaledBitmap(bitmap, 100, 100, true)

      // LabelOptions 생성
      val labelOptions = LabelOptions.from(pos).setStyles(LabelStyle.from(scaledBitmap))

      // 레이블 추가
      labelLayer.addLabel(labelOptions)

      Log.d("KakaoMap", "Waypoint label added at: $latitude, $longitude")
    } else {
      Log.e("KakaoMap", "KakaoMap is not initialized")
    }
  }

  private fun drawRouteLineWithWaypoints(startLat: Double, startLng: Double, endLat: Double, endLng: Double, waypoints: List<Map<String, Double>>) {
    if (isMapReady) {
      val startLatLng = LatLng.from(startLat, startLng)
      val endLatLng = LatLng.from(endLat, endLng)

      val waypointLatLngs = waypoints.map { LatLng.from(it["latitude"]!!, it["longitude"]!!) }
      Log.d("RouteLine", "Waypoints: $waypointLatLngs")  // 경유지 좌표 확인

      val allPoints = mutableListOf(startLatLng).apply {
        addAll(waypointLatLngs)
        add(endLatLng)
      }

      Log.d("RouteLine", "All route points: $allPoints")  // 모든 경로 좌표 확인

      val routeLineStyle = RouteLineStyle.from(16f, Color.BLUE)
      val segment = RouteLineSegment.from(allPoints).setStyles(routeLineStyle)

      val routeLineOptions = RouteLineOptions.from(listOf(segment))
      val layer = kakaoMap.getRouteLineManager()?.getLayer()
      layer?.addRouteLine(routeLineOptions)

      Log.d("RouteLine", "Route line with waypoints drawn successfully")
    } else {
      Log.e("KakaoMap", "Map is not ready to draw route line")
    }
  }


  // 경로 전체를 화면에 맞추기 위한 카메라 이동 함수
  private fun moveToFitRoute(points: Array<LatLng>) {
    if (isMapReady) {
      val cameraUpdate = CameraUpdateFactory.fitMapPoints(points)
      kakaoMap.moveCamera(cameraUpdate)

      Log.d("KakaoMap", "Camera moved to fit route: $points")  // 카메라 이동 확인
    } else {
      Log.e("KakaoMap", "KakaoMap is not initialized")
    }
  }

  private fun getAppKeyHash() {
    try {
      val info = packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES)
      for (signature in info.signatures) {
        val md = MessageDigest.getInstance("SHA")
        md.update(signature.toByteArray())
        val something = String(Base64.encode(md.digest(), 0))
        Log.e("Hash key", something)
      }
    } catch (e: Exception) {
      Log.e("name not found", e.toString())
    }
  }

  override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
    super.configureFlutterEngine(flutterEngine)
    flutterEngine
      .platformViewsController
      .registry
      .registerViewFactory("KakaoMapView", KakaoMapFactory(this))
  }
}

class KakaoMapFactory(private val activity: Activity) : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
  override fun create(context: Context?, viewId: Int, args: Any?): PlatformView {
    val mapView = MapView(activity)
    (activity as MainActivity).mapView = mapView

    mapView.start(object : MapLifeCycleCallback() {
      override fun onMapDestroy() {
        Log.d("KakaoMap", "Map destroyed")
      }

      override fun onMapError(error: Exception) {
        Log.e("KakaoMap", "Map error: ${error.message}")
      }
    }, object : KakaoMapReadyCallback() {
      override fun onMapReady(map: KakaoMap) {
        (activity as MainActivity).kakaoMap = map
        (activity as MainActivity).isMapReady = true  // 지도 준비 완료 플래그 설정
        Log.d("KakaoMap", "KakaoMap is ready")
      }
    })
    val creationParams = args as Map<String, Any>
    val startLatitude = creationParams["startLatitude"] as? Double
    val startLongitude = creationParams["startLongitude"] as? Double
    val endLatitude = creationParams["endLatitude"] as? Double
    val endLongitude = creationParams["endLongitude"] as? Double

    if (startLatitude != null && startLongitude != null) {
      activity.addLabel(startLatitude, startLongitude, true)  // 출발지
    }
    if (endLatitude != null && endLongitude != null) {
      activity.addLabel(endLatitude, endLongitude, false)  // 도착지
    }

    return KakaoMapView(mapView)
  }
}

class KakaoMapView(private val mapView: MapView) : PlatformView {
  override fun getView(): View {
    return mapView
  }

  override fun dispose() {}
}

현재 제가 사용하고 있는 kotlin 코드입니다.

이런식으로 사용하고 있는데 경유지 없이 길찾기는 가능한데 경유지를 추가하는 순간 routeline이 그려지지 않는 문제가 발생합니다.

또한 라벨 초기화 방식에도 문제가 있는지 라벨을 한번 찍고 나면 재생성이 안되는데… 어떻게 하면 좋을지 방향을 잡아주시면 감사하겠습니다.

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../activity_main.dart';
import 'activity_bike.dart';
import 'activity_bus.dart';
import 'activity_car.dart';
import 'activity_walk.dart';

class TrafficFragment extends StatefulWidget {
  @override
  _TrafficFragmentState createState() => _TrafficFragmentState();
}

class _TrafficFragmentState extends State<TrafficFragment> {
  int selectedIndex = 1;
  final PageController _pageController = PageController(initialPage: 1);
  final TextEditingController _startController = TextEditingController();
  final TextEditingController _endController = TextEditingController();
  final FocusNode _startFocusNode = FocusNode();
  final FocusNode _endFocusNode = FocusNode();

  // 동적으로 높이를 변경하기 위한 초기값 설정
  double _scrollHeight = 120; // 기본 높이 설정
  bool _isHeightIncreased = false; // 높이가 한번만 200으로 증가되도록 제어하는 변수

  // 경유지 관련 추가 변수들
  final List<TextEditingController> _waypointControllers = [];
  final List<FocusNode> _waypointFocusNodes = [];
  List<MapPoint?> _waypoints = [];
  List<List<dynamic>> _waypointSearchResults = [];

  List<dynamic> _startSearchResults = [];
  List<dynamic> _endSearchResults = [];
  MapPoint? _startPoint;
  MapPoint? _endPoint;

  @override
  void initState() {
    super.initState();
    _startFocusNode.addListener(_onStartFocusChange);
    _endFocusNode.addListener(_onEndFocusChange);
  }

  @override
  void dispose() {
    _startFocusNode.removeListener(_onStartFocusChange);
    _endFocusNode.removeListener(_onEndFocusChange);
    _startFocusNode.dispose();
    _endFocusNode.dispose();
    super.dispose();
  }

  void _onStartFocusChange() {
    if (_startFocusNode.hasFocus) {
      setState(() {
        _endSearchResults.clear();
      });
    }
  }

  void _onEndFocusChange() {
    if (_endFocusNode.hasFocus) {
      setState(() {
        _startSearchResults.clear();
      });
    }
  }

  void _searchStartLocation(String query) async {
    try {
      final String result = await MethodChannel('com.example.easytrip/search')
          .invokeMethod('search', query);
      final data = jsonDecode(result);
      setState(() {
        _startSearchResults = data['documents'];
      });
    } on PlatformException catch (e) {
      print('Failed to search: ${e.message}');
    }
  }

  void _searchEndLocation(String query) async {
    try {
      final String result = await MethodChannel('com.example.easytrip/search')
          .invokeMethod('search', query);
      final data = jsonDecode(result);
      setState(() {
        _endSearchResults = data['documents'];
      });
    } on PlatformException catch (e) {
      print('Failed to search: ${e.message}');
    }
  }

  void _searchWaypointLocation(String query, int index) async {
    try {
      final String result = await MethodChannel('com.example.easytrip/search')
          .invokeMethod('search', query);
      final data = jsonDecode(result);
      setState(() {
        _waypointSearchResults[index] = data['documents'];
      });
    } on PlatformException catch (e) {
      print('Failed to search: ${e.message}');
    }
  }

  void _onStartPlaceTap(dynamic place) {
    _startController.text = place['place_name'];
    setState(() {
      _startPoint = MapPoint(
        latitude: double.parse(place['y']),
        longitude: double.parse(place['x']),
      );
      _startSearchResults.clear();
    });

    print('출발지 선택: ${_startPoint!.latitude}, ${_startPoint!.longitude}');
  }

  void _onEndPlaceTap(dynamic place) {
    _endController.text = place['place_name'];
    setState(() {
      _endPoint = MapPoint(
        latitude: double.parse(place['y']),
        longitude: double.parse(place['x']),
      );
      _endSearchResults.clear();
    });

    print('도착지 선택: ${_endPoint!.latitude}, ${_endPoint!.longitude}');
  }

  void _onWaypointPlaceTap(dynamic place, int index) {
    _waypointControllers[index].text = place['place_name'];
    setState(() {
      _waypoints[index] = MapPoint(
        latitude: double.parse(place['y']),
        longitude: double.parse(place['x']),
      );
      _waypointSearchResults[index].clear();
    });
  }

  void addWaypoints(List<Map<String, double>> waypoints) {
    MethodChannel('com.example.easytrip/map').invokeMethod('addWaypoints', waypoints);
  }

  void drawRouteWithWaypoints(double startLat, double startLng, double endLat, double endLng, List<Map<String, double>> waypoints) {
    MethodChannel('com.example.easytrip/map').invokeMethod('drawRouteWithWaypoints', {
      'startLatitude': startLat,
      'startLongitude': startLng,
      'endLatitude': endLat,
      'endLongitude': endLng,
      'waypoints': waypoints,
    });
  }


  void _swapLocations() {
    setState(() {
      String tempText = _startController.text;
      _startController.text = _endController.text;
      _endController.text = tempText;

      MapPoint? tempPoint = _startPoint;
      _startPoint = _endPoint;
      _endPoint = tempPoint;

      print("Swapped: 출발지 -> ${_startPoint?.latitude}, ${_startPoint?.longitude}, 도착지 -> ${_endPoint?.latitude}, ${_endPoint?.longitude}");

      MethodChannel('com.example.easytrip/map').invokeMethod('removeLabel');
      _showRoute();
    });
  }

  void _addWaypoint() {
    setState(() {
      _waypointControllers.add(TextEditingController());
      _waypointFocusNodes.add(FocusNode());
      _waypoints.add(null);
      _waypointSearchResults.add([]);

      // 경유지가 추가될 때 높이가 200으로 한 번만 증가
      if (!_isHeightIncreased) {
        _scrollHeight = 200;
        _isHeightIncreased = true;
      }
    });
  }

  void _removeWaypoint(int index) {
    setState(() {
      _waypointControllers.removeAt(index);
      _waypointFocusNodes.removeAt(index);
      _waypoints.removeAt(index);
      _waypointSearchResults.removeAt(index);

      // 경유지가 모두 삭제되면 높이를 다시 120으로 설정
      if (_waypointControllers.isEmpty) {
        _scrollHeight = 120;
        _isHeightIncreased = false;
      }
    });
  }

  // drawRouteLine 호출 부분 수정
  void _showRoute() {
    if (_startPoint != null && _endPoint != null) {
      double startLat = _startPoint!.latitude;
      double startLng = _startPoint!.longitude;
      double endLat = _endPoint!.latitude;
      double endLng = _endPoint!.longitude;

      // 경유지 리스트를 구성
      List<Map<String, dynamic>> waypointCoords = [];
      for (var waypoint in _waypoints) {
        if (waypoint != null) {
          waypointCoords.add({
            'latitude': waypoint.latitude,
            'longitude': waypoint.longitude,
          });
        }
      }

      // 선택된 교통수단에 맞는 메소드 설정
      String methodToCall;
      switch (selectedIndex) {
        case 0:
          methodToCall = 'getCarRoute';
          break;
        case 1:
          methodToCall = 'getBusRoute';
          break;
        case 2:
          methodToCall = 'getWalkingRoute';
          break;
        case 3:
          methodToCall = 'getBicycleRoute';
          break;
        default:
          methodToCall = 'drawRouteLine';
      }

      // Start point 설정
      MethodChannel('com.example.easytrip/map').invokeMethod('moveToLocation', {
        'latitude': startLat,
        'longitude': startLng,
        'isStartPoint': true,
      }).then((_) {
        // 출발지 라벨 추가
        MethodChannel('com.example.easytrip/map').invokeMethod('addLabel', {
          'latitude': startLat,
          'longitude': startLng,
          'isStartPoint': true,
        }).then((_) {
          // End point 설정 및 라벨 추가
          MethodChannel('com.example.easytrip/map').invokeMethod('moveToLocation', {
            'latitude': endLat,
            'longitude': endLng,
            'isStartPoint': false,
          }).then((_) {
            // 도착지 라벨 추가
            MethodChannel('com.example.easytrip/map').invokeMethod('addLabel', {
              'latitude': endLat,
              'longitude': endLng,
              'isStartPoint': false,
            }).then((_) {
              // 경유지 라벨 추가
              for (int i = 0; i < waypointCoords.length; i++) {
                final waypoint = waypointCoords[i];
                MethodChannel('com.example.easytrip/map').invokeMethod('addLabel', {
                  'latitude': waypoint['latitude'],
                  'longitude': waypoint['longitude'],
                  'isWaypoint': true,  // 경유지임을 표시
                });
              }

              // 경유지 포함한 경로 계산
              MethodChannel('com.example.easytrip/map').invokeMethod(methodToCall, {
                'startLatitude': startLat,
                'startLongitude': startLng,
                'endLatitude': endLat,
                'endLongitude': endLng,
                'waypoints': waypointCoords,
              }).then((_) {
                // 경로 그리기 완료 후 상태 업데이트
                print("Start: $startLat, $startLng, End: $endLat, $endLng, Waypoints: $waypointCoords");
                setState(() {});
              }).catchError((error) {
                print("Error drawing route line: $error");
              });
            });
          });
        });
      });
    } else {
      print("Start or end location is not selected.");
    }
  }

  void _onPageChanged(int index) {
    setState(() {
      selectedIndex = index;
    });
  }

  void _onTransportButtonTapped(int index) {
    setState(() {
      selectedIndex = index;
    });
    _pageController.jumpToPage(index);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: Column(
        children: [
          Container(
            color: Color(0xFF4285F4),
            padding: EdgeInsets.only(top: 50, left: 16, right: 5, bottom: 20),
            child: Column(
              children: [
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceBetween,
                  children: [
                    Expanded(
                      child: Row(
                        mainAxisAlignment: MainAxisAlignment.spaceEvenly,
                        children: [
                          _buildTransportButton(Icons.directions_car, 0),
                          _buildTransportButton(Icons.directions_bus, 1),
                          _buildTransportButton(Icons.directions_walk, 2),
                          _buildTransportButton(Icons.directions_bike, 3),
                        ],
                      ),
                    ),
                    IconButton(
                      icon: Icon(Icons.play_arrow, color: Colors.white),
                      onPressed: _showRoute,
                    ),
                  ],
                ),
                SizedBox(height: 16),

                // 스크롤이 가능한 출발지, 경유지, 도착지 리스트 영역
                Container(
                  height: _scrollHeight,  // 동적으로 변경된 높이를 적용
                  child: SingleChildScrollView(
                    child: Column(
                      children: [
                        // 출발지 필드
                        Row(
                          children: [
                            Expanded(
                              child: TextField(
                                controller: _startController,
                                focusNode: _startFocusNode,
                                style: TextStyle(color: Colors.white),
                                decoration: InputDecoration(
                                  labelText: '출발지',
                                  labelStyle: TextStyle(color: Colors.white),
                                  filled: true,
                                  fillColor: Colors.white.withOpacity(0.2),
                                  border: OutlineInputBorder(
                                    borderSide: BorderSide(color: Colors.white),
                                  ),
                                  enabledBorder: OutlineInputBorder(
                                    borderSide: BorderSide(color: Colors.white),
                                  ),
                                  focusedBorder: OutlineInputBorder(
                                    borderSide: BorderSide(color: Colors.white),
                                  ),
                                ),
                                onChanged: _searchStartLocation,
                              ),
                            ),
                            IconButton(
                              icon: Icon(Icons.swap_vert, color: Colors.white),
                              onPressed: _swapLocations,
                            ),
                          ],
                        ),
                        // 경유지 필드 섹션
                        if (_startSearchResults.isNotEmpty)
                          _buildSearchResults(_startSearchResults, _onStartPlaceTap),
                        _buildWaypointsSection(),  // 경유지 섹션
                        SizedBox(height: 8),
                        // 도착지 필드
                        Row(
                          children: [
                            Expanded(
                              child: TextField(
                                controller: _endController,
                                focusNode: _endFocusNode,
                                style: TextStyle(color: Colors.white),
                                decoration: InputDecoration(
                                  labelText: '도착지',
                                  labelStyle: TextStyle(color: Colors.white),
                                  filled: true,
                                  fillColor: Colors.white.withOpacity(0.2),
                                  border: OutlineInputBorder(
                                    borderSide: BorderSide(color: Colors.white),
                                  ),
                                  enabledBorder: OutlineInputBorder(
                                    borderSide: BorderSide(color: Colors.white),
                                  ),
                                  focusedBorder: OutlineInputBorder(
                                    borderSide: BorderSide(color: Colors.white),
                                  ),
                                ),
                                onChanged: _searchEndLocation,
                              ),
                            ),
                            IconButton(
                              icon: Icon(Icons.add, color: Colors.white),
                              onPressed: _addWaypoint,
                            ),
                          ],
                        ),
                      ],
                    ),
                  ),
                ),

                if (_startSearchResults.isNotEmpty)
                  _buildSearchResults(_startSearchResults, _onStartPlaceTap),
                if (_endSearchResults.isNotEmpty)
                  _buildSearchResults(_endSearchResults, _onEndPlaceTap),
              ],
            ),
          ),

          Expanded(
            child: PageView(
              controller: _pageController,
              onPageChanged: _onPageChanged,
              physics: NeverScrollableScrollPhysics(),
              children: [
                CarPage(
                  refreshData: () async {},
                  startPoint: _startPoint,
                  endPoint: _endPoint,
                ),
                BusPage(),
                WalkPage(
                  refreshData: () async {},
                  startPoint: _startPoint,
                  endPoint: _endPoint,
                ),
                BikePage(),
              ],
            ),
          ),
        ],
      ),
    );
  }

  // 경유지 섹션 빌드
  Widget _buildWaypointsSection() {
    return Column(
      children: [
        for (int i = 0; i < _waypointControllers.length; i++)
          Padding(
            padding: const EdgeInsets.only(top: 8.0), // 필드 간 간격 조정
            child: Column(
              children: [
                Row(
                  children: [
                    Expanded(
                      child: Stack(
                        children: [
                          TextField(
                            controller: _waypointControllers[i],
                            focusNode: _waypointFocusNodes[i],
                            style: TextStyle(color: Colors.white),
                            decoration: InputDecoration(
                              labelText: '경유지',
                              labelStyle: TextStyle(color: Colors.white),
                              filled: true,
                              fillColor: Colors.white.withOpacity(0.2),
                              border: OutlineInputBorder(
                                borderSide: BorderSide(color: Colors.white),
                              ),
                              enabledBorder: OutlineInputBorder(
                                borderSide: BorderSide(color: Colors.white),
                              ),
                              focusedBorder: OutlineInputBorder(
                                borderSide: BorderSide(color: Colors.white),
                              ),
                            ),
                            onChanged: (query) => _searchWaypointLocation(query, i), // 경유지 검색 호출
                          ),
                          Positioned(
                            right: 8,
                            top: 6,
                            child: IconButton(
                              icon: Icon(Icons.remove, color: Colors.white),
                              onPressed: () => _removeWaypoint(i),
                            ),
                          ),
                        ],
                      ),
                    ),
                    SizedBox(width: 12), // 스왑 버튼과 필드 사이 간격 조절
                    Icon(Icons.swap_vert, color: Colors.white), // 드래그 앤 드롭 버튼
                    SizedBox(width: 12), // 스왑 버튼과 필드 사이 간격 조절
                  ],
                ),
                // 경유지 검색 결과 표시
                if (_waypointSearchResults[i].isNotEmpty) _buildWaypointSearchResults(i),
              ],
            ),
          ),
      ],
    );
  }

  // 검색 결과 빌드
  Widget _buildSearchResults(List<dynamic> searchResults, Function(dynamic) onTap) {
    return Align(
      alignment: Alignment.centerLeft,
      child: Container(
        color: Colors.white,
        height: 180,
        width: 343,
        child: ListView.builder(
          padding: EdgeInsets.only(top: 5),
          itemCount: searchResults.length,
          itemBuilder: (context, index) {
            final place = searchResults[index];
            return ListTile(
              title: Text(place['place_name']),
              subtitle: Text(place['address_name']),
              onTap: () => onTap(place),
            );
          },
        ),
      ),
    );
  }

  Widget _buildWaypointSearchResults(int index) {
    // 경유지별로 고유한 검색 결과 리스트를 가져옴
    List<dynamic> searchResults = _waypointSearchResults[index];

    if (searchResults.isEmpty) return SizedBox.shrink();  // 검색 결과가 없으면 아무것도 보여주지 않음

    return Align(
      alignment: Alignment.centerLeft,
      child: Container(
        color: Colors.white,
        height: 180,
        width: 343,
        child: ListView.builder(
          padding: EdgeInsets.only(top: 5),
          itemCount: searchResults.length,
          itemBuilder: (context, resultIndex) {
            final place = searchResults[resultIndex];
            return ListTile(
              title: Text(place['place_name']),
              subtitle: Text(place['address_name']),
              onTap: () => _onWaypointPlaceTap(place, index), // 경유지 필드 인덱스에 맞는 선택 처리
            );
          },
        ),
      ),
    );
  }


  Widget _buildTransportButton(IconData icon, int index) {
    return Container(
      decoration: BoxDecoration(
        color: selectedIndex == index ? Colors.white : Colors.transparent,
        borderRadius: BorderRadius.circular(20.0),
      ),
      padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
      child: InkWell(
        onTap: () => _onTransportButtonTapped(index),
        child: Icon(
          icon,
          color: selectedIndex == index ? Colors.blue : Colors.white,
        ),
      ),
    );
  }
}

class MapPoint {
  final double latitude;
  final double longitude;

  MapPoint({required this.latitude, required this.longitude});
}```


추가적인 flutter 코드입니다.