diff --git a/presentation/src/main/AndroidManifest.xml b/presentation/src/main/AndroidManifest.xml
index 6def8511..f4ae951c 100644
--- a/presentation/src/main/AndroidManifest.xml
+++ b/presentation/src/main/AndroidManifest.xml
@@ -1,6 +1,11 @@
+
+
+
+
+
-
-
-
diff --git a/presentation/src/main/java/com/cheocharm/presentation/common/Constants.kt b/presentation/src/main/java/com/cheocharm/presentation/common/Constants.kt
index f6bf8c53..c5772c83 100644
--- a/presentation/src/main/java/com/cheocharm/presentation/common/Constants.kt
+++ b/presentation/src/main/java/com/cheocharm/presentation/common/Constants.kt
@@ -3,3 +3,8 @@ package com.cheocharm.presentation.common
const val SIGN_UP_TYPE = "signUpType"
const val GOOGLE_ID_TOKEN = "googleIdToken"
const val GROUP_JOIN_REQUEST_BOTTOM = "groupJoinRequestBottom"
+
+const val SOUTH_KOREA_LAT = 35.95
+const val SOUTH_KOREA_LNG = 128.25
+const val SOUTH_KOREA_ZOOM_LEVEL = 6.5F
+const val DEFAULT_ZOOM_LEVEL = 15F
diff --git a/presentation/src/main/java/com/cheocharm/presentation/common/Extensions.kt b/presentation/src/main/java/com/cheocharm/presentation/common/Extensions.kt
new file mode 100644
index 00000000..abe25558
--- /dev/null
+++ b/presentation/src/main/java/com/cheocharm/presentation/common/Extensions.kt
@@ -0,0 +1,6 @@
+package com.cheocharm.presentation.common
+
+import android.location.Location
+import com.google.android.gms.maps.model.LatLng
+
+fun Location.toLatLng() = LatLng(this.latitude, this.longitude)
diff --git a/presentation/src/main/java/com/cheocharm/presentation/common/ext.kt b/presentation/src/main/java/com/cheocharm/presentation/common/ext.kt
deleted file mode 100644
index a865a2ac..00000000
--- a/presentation/src/main/java/com/cheocharm/presentation/common/ext.kt
+++ /dev/null
@@ -1,11 +0,0 @@
-package com.cheocharm.presentation.common
-
-import com.google.android.gms.maps.model.LatLng
-
-fun LatLng?.toCoordString() = this?.let {
- with("%.5f") {
- val lat = format(it.latitude)
- val lng = format(it.longitude)
- "($lat, $lng)"
- }
-}
diff --git a/presentation/src/main/java/com/cheocharm/presentation/enum/LatLngSelectionType.kt b/presentation/src/main/java/com/cheocharm/presentation/enum/LatLngSelectionType.kt
new file mode 100644
index 00000000..8db5f85e
--- /dev/null
+++ b/presentation/src/main/java/com/cheocharm/presentation/enum/LatLngSelectionType.kt
@@ -0,0 +1,7 @@
+package com.cheocharm.presentation.enum
+
+enum class LatLngSelectionType(val locationString: String) {
+ DEFAULT("대한민국"),
+ CURRENT("현재 위치"),
+ SPECIFIED("")
+}
diff --git a/presentation/src/main/java/com/cheocharm/presentation/model/Picture.kt b/presentation/src/main/java/com/cheocharm/presentation/model/Picture.kt
index 67b88c02..d23b509a 100644
--- a/presentation/src/main/java/com/cheocharm/presentation/model/Picture.kt
+++ b/presentation/src/main/java/com/cheocharm/presentation/model/Picture.kt
@@ -1,13 +1,8 @@
package com.cheocharm.presentation.model
import android.net.Uri
-import com.cheocharm.presentation.common.toCoordString
import com.google.android.gms.maps.model.LatLng
data class Picture(val uri: Uri, val latLng: LatLng?) {
var address: String? = null
-
- fun getLocationString(): String {
- return address ?: latLng.toCoordString() ?: "현재 위치"
- }
}
diff --git a/presentation/src/main/java/com/cheocharm/presentation/ui/MainActivity.kt b/presentation/src/main/java/com/cheocharm/presentation/ui/MainActivity.kt
index fc882bba..07f180d8 100644
--- a/presentation/src/main/java/com/cheocharm/presentation/ui/MainActivity.kt
+++ b/presentation/src/main/java/com/cheocharm/presentation/ui/MainActivity.kt
@@ -1,22 +1,50 @@
package com.cheocharm.presentation.ui
+import android.Manifest
import android.content.Context
import android.graphics.Rect
+import android.os.Build
import android.os.Bundle
import android.view.MotionEvent
import android.view.View
import android.view.inputmethod.InputMethodManager
import android.widget.EditText
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.annotation.RequiresApi
import androidx.core.view.isVisible
import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.setupWithNavController
import com.cheocharm.presentation.R
import com.cheocharm.presentation.base.BaseActivity
import com.cheocharm.presentation.databinding.ActivityMainBinding
+import com.google.android.gms.location.FusedLocationProviderClient
+import com.google.android.gms.location.LocationServices
+import com.google.android.gms.maps.SupportMapFragment
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class MainActivity : BaseActivity(R.layout.activity_main) {
+ private var mapFragment: SupportMapFragment? = null
+ private var fusedLocationClient: FusedLocationProviderClient? = null
+
+ @RequiresApi(Build.VERSION_CODES.N)
+ private val locationPermissionRequest = registerForActivityResult(
+ ActivityResultContracts.RequestMultiplePermissions()
+ ) { permissions ->
+ when {
+ permissions[Manifest.permission.ACCESS_FINE_LOCATION] ?: false -> {
+ fusedLocationClient =
+ LocationServices.getFusedLocationProviderClient(this)
+ }
+ permissions[Manifest.permission.ACCESS_COARSE_LOCATION] ?: false -> {
+ fusedLocationClient =
+ LocationServices.getFusedLocationProviderClient(this)
+ }
+ else -> {
+ // TODO: 위치 권한을 얻지 못했을 때
+ }
+ }
+ }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -37,6 +65,21 @@ class MainActivity : BaseActivity(R.layout.activity_main) {
binding.bottomNavMain.visibility = View.VISIBLE
}
}
+
+ mapFragment =
+ supportFragmentManager.findFragmentById(R.id.fragment_main_map) as? SupportMapFragment
+ }
+
+ @RequiresApi(Build.VERSION_CODES.N)
+ override fun onStart() {
+ super.onStart()
+
+ locationPermissionRequest.launch(
+ arrayOf(
+ Manifest.permission.ACCESS_FINE_LOCATION,
+ Manifest.permission.ACCESS_COARSE_LOCATION
+ )
+ )
}
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
@@ -60,4 +103,12 @@ class MainActivity : BaseActivity(R.layout.activity_main) {
}
fun getBinding(): ActivityMainBinding = binding
+
+ fun setMapVisible(boolean: Boolean) {
+ binding.fragmentMainMap.isVisible = boolean
+ }
+
+ fun getMap(): SupportMapFragment? = mapFragment
+
+ fun getLocationClient(): FusedLocationProviderClient? = fusedLocationClient
}
diff --git a/presentation/src/main/java/com/cheocharm/presentation/ui/home/HomeFragment.kt b/presentation/src/main/java/com/cheocharm/presentation/ui/home/HomeFragment.kt
index 54b4d5ba..034a599b 100644
--- a/presentation/src/main/java/com/cheocharm/presentation/ui/home/HomeFragment.kt
+++ b/presentation/src/main/java/com/cheocharm/presentation/ui/home/HomeFragment.kt
@@ -1,13 +1,23 @@
package com.cheocharm.presentation.ui.home
+import android.Manifest
+import android.content.pm.PackageManager
import android.os.Bundle
import android.view.View
-import androidx.core.view.isVisible
+import androidx.core.content.ContextCompat
import androidx.fragment.app.viewModels
import com.cheocharm.presentation.R
import com.cheocharm.presentation.base.BaseFragment
+import com.cheocharm.presentation.common.DEFAULT_ZOOM_LEVEL
+import com.cheocharm.presentation.common.SOUTH_KOREA_LAT
+import com.cheocharm.presentation.common.SOUTH_KOREA_LNG
+import com.cheocharm.presentation.common.SOUTH_KOREA_ZOOM_LEVEL
+import com.cheocharm.presentation.common.toLatLng
import com.cheocharm.presentation.databinding.FragmentHomeBinding
import com.cheocharm.presentation.ui.MainActivity
+import com.google.android.gms.maps.CameraUpdateFactory
+import com.google.android.gms.maps.GoogleMap
+import com.google.android.gms.maps.model.LatLng
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
@@ -19,9 +29,47 @@ class HomeFragment : BaseFragment(R.layout.fragment_home) {
binding.viewmodel = homeViewModel
- val mainActivityBinding = (activity as MainActivity).getBinding()
- mainActivityBinding.fragmentMainMap.isVisible = true
+ val mainActivity = requireActivity() as MainActivity
+ mainActivity.setMapVisible(true)
- homeViewModel.countUp()
+ val mapFragment = (activity as MainActivity).getMap()
+ mapFragment?.getMapAsync { map ->
+ map.setOnCameraMoveListener {
+ homeViewModel.updateZoomLevel(map.cameraPosition.zoom)
+ }
+
+ map.setOnMapLoadedCallback {
+ if (ContextCompat.checkSelfPermission(
+ requireContext(),
+ Manifest.permission.ACCESS_FINE_LOCATION
+ ) == PackageManager.PERMISSION_GRANTED
+ ) {
+ val locationClient = mainActivity.getLocationClient()
+ locationClient?.lastLocation?.addOnSuccessListener { location ->
+ if (location != null) {
+ map.moveCamera(
+ CameraUpdateFactory.newLatLngZoom(
+ location.toLatLng(),
+ DEFAULT_ZOOM_LEVEL
+ )
+ )
+ } else {
+ map.moveCameraToDefaultLocation()
+ }
+ }
+ } else {
+ map.moveCameraToDefaultLocation()
+ }
+ }
+ }
+ }
+
+ private fun GoogleMap.moveCameraToDefaultLocation() {
+ moveCamera(
+ CameraUpdateFactory.newLatLngZoom(
+ LatLng(SOUTH_KOREA_LAT, SOUTH_KOREA_LNG),
+ SOUTH_KOREA_ZOOM_LEVEL
+ )
+ )
}
}
diff --git a/presentation/src/main/java/com/cheocharm/presentation/ui/home/HomeViewModel.kt b/presentation/src/main/java/com/cheocharm/presentation/ui/home/HomeViewModel.kt
index 22d320cb..cea5c91d 100644
--- a/presentation/src/main/java/com/cheocharm/presentation/ui/home/HomeViewModel.kt
+++ b/presentation/src/main/java/com/cheocharm/presentation/ui/home/HomeViewModel.kt
@@ -1,5 +1,6 @@
package com.cheocharm.presentation.ui.home
+import android.location.Location
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
@@ -8,10 +9,17 @@ import javax.inject.Inject
@HiltViewModel
class HomeViewModel @Inject constructor() : ViewModel() {
- private val _count = MutableLiveData()
- val count: LiveData = _count
+ private val _location = MutableLiveData()
+ val location: LiveData = _location
- fun countUp() {
- _count.value = count.value?.plus(1) ?: 1
+ private val _zoomLevel = MutableLiveData()
+ val zoomLevel: LiveData = _zoomLevel
+
+ fun updateLocation(location: Location) {
+ _location.value = location
+ }
+
+ fun updateZoomLevel(level: Float) {
+ _zoomLevel.value = level
}
}
diff --git a/presentation/src/main/java/com/cheocharm/presentation/ui/mypage/MyPageFragment.kt b/presentation/src/main/java/com/cheocharm/presentation/ui/mypage/MyPageFragment.kt
index cebdda9f..5ef9e047 100644
--- a/presentation/src/main/java/com/cheocharm/presentation/ui/mypage/MyPageFragment.kt
+++ b/presentation/src/main/java/com/cheocharm/presentation/ui/mypage/MyPageFragment.kt
@@ -3,7 +3,6 @@ package com.cheocharm.presentation.ui.mypage
import android.content.Intent
import android.os.Bundle
import android.view.View
-import androidx.core.view.isVisible
import androidx.fragment.app.viewModels
import com.cheocharm.presentation.BuildConfig
import com.cheocharm.presentation.R
@@ -38,8 +37,8 @@ class MyPageFragment : BaseFragment(R.layout.fragment_my_
binding.viewmodel = myPageViewModel
- val mainActivityBinding = (activity as MainActivity).getBinding()
- mainActivityBinding.fragmentMainMap.isVisible = false
+ val mainActivity = requireActivity() as MainActivity
+ mainActivity.setMapVisible(false)
initButton()
myPageViewModel.countUp()
diff --git a/presentation/src/main/java/com/cheocharm/presentation/ui/search/SearchFragment.kt b/presentation/src/main/java/com/cheocharm/presentation/ui/search/SearchFragment.kt
index 5290305d..7d976eca 100644
--- a/presentation/src/main/java/com/cheocharm/presentation/ui/search/SearchFragment.kt
+++ b/presentation/src/main/java/com/cheocharm/presentation/ui/search/SearchFragment.kt
@@ -3,7 +3,6 @@ package com.cheocharm.presentation.ui.search
import android.os.Bundle
import android.view.View
import android.view.inputmethod.EditorInfo
-import androidx.core.view.isVisible
import androidx.hilt.navigation.fragment.hiltNavGraphViewModels
import androidx.navigation.fragment.findNavController
import com.cheocharm.presentation.R
@@ -24,7 +23,9 @@ class SearchFragment : BaseFragment(R.layout.fragment_sea
binding.viewmodel = searchViewModel
- mainActivityBinding = (activity as MainActivity).getBinding()
+ val mainActivity = requireActivity() as MainActivity
+ mainActivity.setMapVisible(false)
+ mainActivityBinding = mainActivity.getBinding()
initEditTexts()
initObservers()
@@ -32,8 +33,6 @@ class SearchFragment : BaseFragment(R.layout.fragment_sea
override fun onResume() {
super.onResume()
-
- mainActivityBinding.fragmentMainMap.isVisible = false
mainActivityBinding.bottomNavMain.visibility = View.VISIBLE
}
diff --git a/presentation/src/main/java/com/cheocharm/presentation/ui/write/LocationFragment.kt b/presentation/src/main/java/com/cheocharm/presentation/ui/write/LocationFragment.kt
index b1d4a386..0de0a84f 100644
--- a/presentation/src/main/java/com/cheocharm/presentation/ui/write/LocationFragment.kt
+++ b/presentation/src/main/java/com/cheocharm/presentation/ui/write/LocationFragment.kt
@@ -1,5 +1,9 @@
package com.cheocharm.presentation.ui.write
+import android.Manifest
+import android.content.pm.PackageManager
+import android.location.Location
+import android.net.Uri
import android.os.Bundle
import android.view.LayoutInflater
import android.view.Menu
@@ -8,42 +12,65 @@ import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
+import androidx.core.content.ContextCompat
import androidx.core.view.MenuHost
import androidx.core.view.MenuProvider
-import androidx.core.view.isVisible
import androidx.lifecycle.Lifecycle
import androidx.navigation.fragment.findNavController
import androidx.navigation.navGraphViewModels
import com.cheocharm.presentation.R
import com.cheocharm.presentation.base.BaseFragment
+import com.cheocharm.presentation.common.DEFAULT_ZOOM_LEVEL
import com.cheocharm.presentation.common.EventObserver
+import com.cheocharm.presentation.common.SOUTH_KOREA_LAT
+import com.cheocharm.presentation.common.SOUTH_KOREA_LNG
+import com.cheocharm.presentation.common.SOUTH_KOREA_ZOOM_LEVEL
+import com.cheocharm.presentation.common.toLatLng
import com.cheocharm.presentation.databinding.FragmentLocationBinding
+import com.cheocharm.presentation.enum.LatLngSelectionType
+import com.cheocharm.presentation.model.Picture
import com.cheocharm.presentation.ui.MainActivity
-import com.cheocharm.presentation.util.UriUtil
-import com.google.android.gms.maps.SupportMapFragment
+import com.cheocharm.presentation.util.GeocodeUtil
+import com.google.android.gms.maps.CameraUpdateFactory
+import com.google.android.gms.maps.GoogleMap
import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.Marker
+import com.google.android.gms.maps.model.MarkerOptions
import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.Dispatchers
import java.io.File
@AndroidEntryPoint
class LocationFragment : BaseFragment(R.layout.fragment_location),
MenuProvider {
- private val pictureViewModel by navGraphViewModels(R.id.write)
private val locationViewModel by navGraphViewModels(R.id.write) { defaultViewModelProviderFactory }
private val writeViewModel by navGraphViewModels(R.id.write) { defaultViewModelProviderFactory }
+ private lateinit var map: GoogleMap
+ private lateinit var geocodeUtil: GeocodeUtil
+
+ private var initialLatLng: LatLng? = null
+ private var initialType: LatLngSelectionType? = null
+
private var draggableMarker: Marker? = null
private var address: String? = null
private var location: LatLng? = null
private var file: File? = null
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ geocodeUtil = GeocodeUtil(requireContext(), Dispatchers.IO)
+
+ setHasOptionsMenu(true)
+ }
+
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
- val menuHost: MenuHost = requireActivity() as MenuHost
+ val menuHost: MenuHost = requireActivity()
menuHost.addMenuProvider(this, viewLifecycleOwner, Lifecycle.State.RESUMED)
return super.onCreateView(inflater, container, savedInstanceState)
@@ -53,15 +80,14 @@ class LocationFragment : BaseFragment(R.layout.fragment
super.onViewCreated(view, savedInstanceState)
val picturesAdapter = PicturesAdapter()
+ val mainActivity = requireActivity() as MainActivity
- binding.viewmodel = pictureViewModel
+ binding.viewmodel = locationViewModel
binding.rvLocationPictures.apply {
adapter = picturesAdapter
}
with(binding.toolbarLocation) {
- val mainActivity = activity as MainActivity
-
mainActivity.setSupportActionBar(this)
setNavigationIcon(R.drawable.ic_back)
setNavigationOnClickListener {
@@ -69,50 +95,150 @@ class LocationFragment : BaseFragment(R.layout.fragment
}
}
- val mainActivityBinding = (activity as MainActivity).getBinding()
- mainActivityBinding.fragmentMainMap.isVisible = true
-
- val mapFragment =
- requireActivity().supportFragmentManager.findFragmentById(R.id.fragment_main_map) as? SupportMapFragment
- mapFragment?.getMapAsync {
- it.setOnMapLoadedCallback {
- // TODO: 마커 생성
-// val selectedLocation = pic.latLng
-// if (selectedLocation != null) {
-// val markerOptions = MarkerOptions()
-// .position(selectedLocation)
-// .draggable(true)
-// draggableMarker = it.addMarker(markerOptions)
-// it.moveCamera(CameraUpdateFactory.newLatLngZoom(selectedLocation, 15F))
-// } else {
-// // TODO: 사진에 장소 정보가 없으면 기본 위치로 카메라 이동
-// }
- }
- }
+ if (savedInstanceState != null) {
+ with(savedInstanceState) {
+ val uri = getString(KEY_URI)
+ val lat = getString(KEY_LAT)?.toDoubleOrNull()
+ val lng = getString(KEY_LNG)?.toDoubleOrNull()
+ val isDefaultLocation = getBoolean(KEY_IS_DEFAULT_LOCATION)
- pictureViewModel.picture.observe(viewLifecycleOwner) { picture ->
- picture?.let { pic ->
- picturesAdapter.submitList(listOf(pic))
+ if (uri != null) {
+ val latLng = if (lat != null && lng != null) LatLng(lat, lng) else null
+ val picture = Picture(Uri.parse(uri), latLng)
- address = pic.address
- location = pic.latLng
+ locationViewModel.loadPicture(picture, geocodeUtil)
+ }
- activity?.applicationContext?.let { context ->
- file = UriUtil.getFileFromUri(context, pic.uri)
+ if (isDefaultLocation) {
+ val typeDefault = LatLngSelectionType.DEFAULT
+ initialType = typeDefault
+ locationViewModel.setSelectedLatLng(defaultLatLng.toDoubleArray(), typeDefault)
}
}
}
+ setupMap(mainActivity, picturesAdapter)
setupToast()
setupNavigation()
}
+ private fun setupMap(
+ mainActivity: MainActivity,
+ picturesAdapter: PicturesAdapter
+ ) {
+ mainActivity.setMapVisible(true)
+
+ val mapFragment = mainActivity.getMap()
+ mapFragment?.getMapAsync { googleMap ->
+ map = googleMap
+
+ googleMap.setOnMapLoadedCallback {
+ val top = binding.toolbarLocation.height
+ val bottom = binding.containerLocationPictures.height
+ googleMap.setPadding(0, top, 0, bottom)
+
+ locationViewModel.picture.observe(viewLifecycleOwner) { picture ->
+ picture?.let { pic ->
+ picturesAdapter.submitList(listOf(pic))
+
+ val selectedLatLng = pic.latLng
+
+ if (selectedLatLng != null) {
+ initTypeToSpecified(selectedLatLng)
+ } else if (ContextCompat.checkSelfPermission(
+ requireContext(),
+ Manifest.permission.ACCESS_FINE_LOCATION
+ ) == PackageManager.PERMISSION_GRANTED
+ ) {
+ val locationClient = mainActivity.getLocationClient()
+ locationClient?.lastLocation?.addOnSuccessListener { location ->
+ if (location != null) {
+ initTypeToCurrent(location.toLatLng())
+ } else {
+ initTypeToDefault()
+ }
+ }
+ } else {
+ initTypeToDefault()
+ }
+ }
+ }
+ }
+
+ googleMap.setOnCameraMoveListener {
+ val latLng = map.cameraPosition.target
+ locationViewModel.setSelectedLatLng(
+ latLng.toDoubleArray(),
+ LatLngSelectionType.SPECIFIED
+ )
+ }
+
+ googleMap.setOnCameraIdleListener {
+ val latLng = map.cameraPosition.target
+ val type = if (initialLatLng != null &&
+ distanceBetween(initialLatLng!!, latLng) <= 1
+ ) {
+ initialType ?: LatLngSelectionType.SPECIFIED
+ } else {
+ LatLngSelectionType.SPECIFIED
+ }
+ val array = latLng.toDoubleArray()
+
+ if (type == LatLngSelectionType.SPECIFIED) {
+ locationViewModel.geocode(geocodeUtil, array, type)
+ } else {
+ locationViewModel.setSelectedLatLng(array, type)
+ }
+ }
+ }
+ }
+
+ private fun initTypeToSpecified(latLng: LatLng) {
+ locationViewModel.geocode(
+ geocodeUtil,
+ latLng.toDoubleArray(),
+ LatLngSelectionType.SPECIFIED
+ )
+ }
+
private fun setupToast() {
locationViewModel.toastText.observe(viewLifecycleOwner, EventObserver {
Toast.makeText(context, it, Toast.LENGTH_SHORT).show()
})
}
+ private fun initTypeToCurrent(latLng: LatLng) {
+ locationViewModel.setSelectedLatLng(latLng.toDoubleArray(), LatLngSelectionType.CURRENT)
+
+ initialLatLng = latLng
+ initialType = LatLngSelectionType.CURRENT
+
+ createMarkerAndMoveCamera(latLng, DEFAULT_ZOOM_LEVEL)
+ }
+
+ private fun initTypeToDefault() {
+ locationViewModel.setSelectedLatLng(
+ defaultLatLng.toDoubleArray(),
+ LatLngSelectionType.DEFAULT
+ )
+
+ initialLatLng = defaultLatLng
+ initialType = LatLngSelectionType.DEFAULT
+
+ createMarkerAndMoveCamera(defaultLatLng, SOUTH_KOREA_ZOOM_LEVEL)
+ }
+
+ private fun LatLng.toDoubleArray(): DoubleArray = doubleArrayOf(latitude, longitude)
+
+ private fun createMarkerAndMoveCamera(latLng: LatLng, zoomLevel: Float) {
+ val markerOptions = MarkerOptions()
+ .position(latLng)
+ .draggable(true)
+ draggableMarker = map.addMarker(markerOptions)
+
+ map.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, zoomLevel))
+ }
+
private fun setupNavigation() {
locationViewModel.locationSelectedEvent.observe(viewLifecycleOwner, EventObserver {
writeViewModel.temp = it
@@ -123,6 +249,19 @@ class LocationFragment : BaseFragment(R.layout.fragment
})
}
+ private fun distanceBetween(latLng1: LatLng, latLng2: LatLng): Float {
+ val result = FloatArray(1)
+ Location.distanceBetween(
+ latLng1.latitude,
+ latLng1.longitude,
+ latLng2.latitude,
+ latLng2.longitude,
+ result
+ )
+
+ return result.first()
+ }
+
override fun onDestroyView() {
draggableMarker?.remove()
super.onDestroyView()
@@ -152,7 +291,43 @@ class LocationFragment : BaseFragment(R.layout.fragment
}
}
+ override fun onSaveInstanceState(outState: Bundle) {
+ val picture = locationViewModel.picture.value
+
+ if (picture != null) {
+ with(outState) {
+ putString(KEY_URI, picture.uri.toString())
+
+ if (picture.latLng != null) {
+ putString(KEY_LAT, picture.latLng.latitude.toString())
+ putString(KEY_LNG, picture.latLng.longitude.toString())
+ }
+
+ val latLng = map.cameraPosition.target
+ val isDefaultLocation = distanceBetween(defaultLatLng, latLng) <= 1
+ putBoolean(KEY_IS_DEFAULT_LOCATION, isDefaultLocation)
+ }
+ }
+
+ super.onSaveInstanceState(outState)
+ }
+
+ override fun onDestroy() {
+ with(map) {
+ setOnCameraMoveListener(null)
+ setOnCameraIdleListener(null)
+ }
+
+ super.onDestroy()
+ }
+
companion object {
+ private val defaultLatLng = LatLng(SOUTH_KOREA_LAT, SOUTH_KOREA_LNG)
+
+ private const val KEY_URI = "uri"
+ private const val KEY_LAT = "lat"
+ private const val KEY_LNG = "lng"
+ private const val KEY_IS_DEFAULT_LOCATION = "isDefaultLocation"
private const val TEST_GROUP_ID = 1L
}
}
diff --git a/presentation/src/main/java/com/cheocharm/presentation/ui/write/LocationViewModel.kt b/presentation/src/main/java/com/cheocharm/presentation/ui/write/LocationViewModel.kt
index 2bc105c6..14afb9a5 100644
--- a/presentation/src/main/java/com/cheocharm/presentation/ui/write/LocationViewModel.kt
+++ b/presentation/src/main/java/com/cheocharm/presentation/ui/write/LocationViewModel.kt
@@ -1,5 +1,6 @@
package com.cheocharm.presentation.ui.write
+import android.os.Build
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
@@ -9,7 +10,10 @@ import com.cheocharm.domain.model.WriteImageRequest
import com.cheocharm.domain.usecase.write.RequestWriteImagesUseCase
import com.cheocharm.presentation.common.Event
import com.cheocharm.presentation.common.TestValues
+import com.cheocharm.presentation.enum.LatLngSelectionType
+import com.cheocharm.presentation.model.Picture
import com.cheocharm.presentation.model.Sticker
+import com.cheocharm.presentation.util.GeocodeUtil
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.launch
import java.io.File
@@ -28,6 +32,64 @@ class LocationViewModel @Inject constructor(
var stickers: List = TestValues.testStickers
private set
+ private val _picture = MutableLiveData