[์กธ์ ์ํ๊ธฐ] Kotlin์์ ์ค์๊ฐ ์์น ๊ธฐ๋ฐ ์ง๋ ์ฐ๋ํ๊ธฐ
๐งจ ์กธ์ ์ํ ํ ํ๋ก์ ํธ, Hear-Hero์ 2์
ํ๋ถ ์กธ์ ์ํ์ ๋ํ ์ด์ผ๊ธฐ๋ฅผ ์ ์ด๋ณด๋ ค ํ๋ค. ์กธ์ ์ดํ ํ๋ฒ์ ์ ๊ธฐ์๋ ๊ธฐ์ต์ด ์ ๋์ง ์๊ฑฐ๋, ์จ์ผ ํ ๋ถ๋์ด ๋ง์ ๊ฒ ๊ฐ์ ์๊ฐ์ด ์์ ๋๋ง๋ค ํ๊ณ ๋ฅผ ์จ๋ณผ ์์ ์ด๋ค.
๐ ํ๋ก ํธ์๋ ์ฝ๋ ๊ฐ๋ฐ
ํ๋ก ํธ์๋์ ํ์ผ ๋ ํฌ์งํ ๋ฆฌ๋ฅผ ์ดํด๋ณด๋ฉด ํฌ๊ฒ main, sounds, map, detail ๋ก ๋๋๋ค. ์ด์ ํด๋นํ๋ ui ์ฝ๋์ event ๋ฑ์ ์์ฑํ๋ ๊ฒ์ด ์ฃผ๋ ์ ๋ฌด์๋ค.
๐ ๋ฅ๋ฌ๋ ์ฝ๋ ๊ฐ๋ฐ
์๋ฆฌ ๋ฐ์ดํฐ ์ ์ ๊ธฐ๋ฐ์ผ๋ก ํน์ ์๋ฆฌ๋ฅผ ์ธ์ํ๊ณ ํ๋ณํ๋ ์ฝ๋๋ฅผ ๊ฐ๋ฐํ๋ ๊ฒ์ด๋ค. ์ด ๋ถ๋ถ์ ์ธ๋๊ฐ ๋งก์ ๋ชจ๋ธ์ ๋น๊ตํ๋ฉฐ ์ฑ๋ฅ์ ์ธก์ ํ๋ ๋ฑ ๋ค์ํ ์ผ์ ํ์ จ๋ค.
๐ง ์์์น ๋ชปํ ์ด๋ ค์ : Place a real time location on Google Map
1. ๊ตฌ๊ธ๋งต API ํค ์ถ๊ฐํ๊ธฐ
API ํค๋ฅผ ๊ฐ์ ธ์จ ํ๋ก import ํด์ผ ํ๋ ๋ถ๋ถ๊ณผ implementation ์์ kotlin ๊ณผ java์ ๋ฐฉ๋ฒ์ด ๋ฌ๋ผ ๊ตฌ๊ธ๋ง์ผ๋ก ํด๊ฒฐํ๋ค. ์ฝค๋ง์ ์์น๋ ๊ดํธ ๋ฑ ์ฌ์ฉ๋ฒ์ด ๋ค๋ฅด๋ค๋ ๊ฒ์ ์๊ฒ ๋์๋ค.
2. ์์ค ์ฝ๋ ์์ฑํ๊ธฐ
fun NavGraphBuilder.mealPlanScreen(
navController: NavController,
bottomBarPadding: PaddingValues,
bottomBarState: MutableState<Boolean>
) {
composable(
route = Navigate.Screen.MealPlan.route
) {
val sigapore = LatLng(1.35, 103.87)
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(sigapore, 10f)
}
var uiSettings by remember{ mutableStateOf(MapUiSettings()) }
bottomBarState.value = true
GoogleMap(
modifier = Modifier
.fillMaxWidth(fraction = 0.8f)
.fillMaxHeight(0.5f),
cameraPositionState = cameraPositionState,
uiSettings = uiSettings
){
}
}
}
์ผ์ฐจ์ ์ผ๋ก ์๋์ ๊ฐ์ GoogleMap import๋ฅผ ํตํด ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ๋ถ๋ฌ์๋ค.
import com.google.maps.android.compose.GoogleMap
์๋จ์ ์ฝ๋๋ฅผ ๋ณด๋ฉด, LatLng์ ๊ณ ์ ๋์ด ์์์ ์ ์ ์๋ค. ์ฌ๊ธฐ์ ์ด๋ฅผ ์ค์๊ฐ ์์น๋ก ๋ณ๊ฒฝํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผ ํ ๊น?
@SuppressLint("MissingPermission")
fun NavGraphBuilder.mealPlanScreen(
navController: NavController,
bottomBarPadding: PaddingValues,
bottomBarState: MutableState<Boolean>,
) {
composable(
route = Navigate.Screen.MealPlan.route
) {
val sigapore = LatLng(1.3139961,103.7041656)
val cameraPositionState = rememberCameraPositionState {
position = CameraPosition.fromLatLngZoom(sigapore, 10f)
}
val locationCallback = object : LocationCallback() {
override fun onLocationResult(locationResult: LocationResult) {
for (location in locationResult.locations){
cameraPositionState.position = CameraPosition.fromLatLngZoom(LatLng(location.latitude, location.longitude), 10f)
}
}
}
val fusedLocationClient = LocationServices.getFusedLocationProviderClient(LocalContext.current)
val locationRequest = LocationRequest.create().apply {
interval = 10000
fastestInterval = 5000
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
fusedLocationClient.requestLocationUpdates(locationRequest,
locationCallback,
Looper.getMainLooper())
val uiSettings by remember{ mutableStateOf(MapUiSettings()) }
bottomBarState.value = true
GoogleMap(
modifier = Modifier
.fillMaxWidth(fraction = 1.0f)
.fillMaxHeight(0.7f),
cameraPositionState = cameraPositionState,
uiSettings = uiSettings
){}
SoundMapButton()
}
}
๋ฐ๋ก fusedLocationClient๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค. FusedLocationProviderClient์์ ๋ง์ง๋ง์ ์ ์ฅ๋ ์์น ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ฌ ์ ์๊ณ , locationCallback์ผ๋ก ์ง๋ ์์ ์์น๋ฅผ ๊ณ์ํด ์ ๋ฐ์ดํธ๊ฐ ๊ฐ๋ฅํ๋ค.
๐ 2์ ํ๊ณ
์คํ์ค๋ฒํ๋ก์ฐ์ ๋์์ ๋ง์ด ๋ฐ์๋ค. ํนํ ์ค์๊ฐ ์์น ์ฐ๋์ ๊ฒฝ์ฐ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ๋ง์์ ์ฌ์ฉ ์ค์ด๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋ค๋ฅธ ๊ฒ์ ์์ค๋ฅผ ๋ ํผ๋ฐ์ค๋ก ์ผ์์ ๋ ์๋ฌ๊ฐ ๋ง์ด ๋ฌ์๋ค. ์ค๊ฐ์๋ LatLng์ด ๋ฐ์์ง์ง ์์ ์ ๋ฝ ๋ฐ๋ค ํ ๊ฐ์ด๋ฐ (0, 0)์ ์๊ธฐ๋ ํ๋ค ^^;; ๊ทธ๋ฆฌ๊ณ UI ์ค๊ณ๋ฅผ ํ ๋ relatative ํ ๊ด๊ณ๋ก ์ฝ๋๋ฅผ ์์ฑํด์ผ ํ๋ฉด์ ํฌ๊ธฐ๊ฐ ๋ฐ๋์ด๋ ๋ชจ์ต์ด ์ด์ํด์ง์ง ์๋๋ค๋ ๊ฒ์ ๋ค์ ํ ๋ฒ ๋๊ผ๋ค. ์์์ ์ฒ์ฒ ์ ๋ฐ๋์ด์ฃผ๋ฉด ์ข์ผ๋ จ๋ง... ใ ใ ๊ทธ๋ผ ๋ค์ ๋ฌ๋ ์์ ์์!