Skip to content

Commit

Permalink
강원대 Android_윤채원 과제 4주차 Step1 (#48)
Browse files Browse the repository at this point in the history
* Initial commit

* 강원대 Android_윤채원 3주차 과제 Step0 (#17)

* Initial commit

* style: Make MainActivity.xml

* feat: make Place.kt and PlaceDBHelper.kt

* feat: add checkPlaceExist of PlaceDBHelper

* feat: modify DB files

* docs: write readme.md

* docs: modify readme.md

* feat: consolidate MVVM pattern

* docs: write readme.md

* style: searchHistory and places cardviews

* style: modify recyclerviews

* feat: implement viewmodel and livedata

* style: modify placemodule

* feat: implement searchHistory

* feat: add search history animation

* feat: implementing search history click

* style: move xml ui string to strings.xml

* check

* delete useless variable

* modify code according to feedback

* move search history methods to repository

* modify README.md

* docs: write readme.md

---------

Co-authored-by: MyStoryG <[email protected]>

* 강원대 Android_윤채원 3주차 과제 Step1 (#43)

* Initial commit

* style: Make MainActivity.xml

* feat: make Place.kt and PlaceDBHelper.kt

* feat: add checkPlaceExist of PlaceDBHelper

* feat: modify DB files

* docs: write readme.md

* docs: modify readme.md

* feat: consolidate MVVM pattern

* docs: write readme.md

* style: searchHistory and places cardviews

* style: modify recyclerviews

* feat: implement viewmodel and livedata

* style: modify placemodule

* feat: implement searchHistory

* feat: add search history animation

* feat: implementing search history click

* style: move xml ui string to strings.xml

* check

* delete useless variable

* modify code according to feedback

* move search history methods to repository

* modify README.md

* docs: write readme.md

* feat: make DTO and retrofitservice interface

* feat: implement api search

* style: long place name shortening

* refactor: move search api method to repository

---------

Co-authored-by: MyStoryG <[email protected]>

* 강원대 Android_윤채원 3주차 과제 Step2 (#89)

* Initial commit

* style: Make MainActivity.xml

* feat: make Place.kt and PlaceDBHelper.kt

* feat: add checkPlaceExist of PlaceDBHelper

* feat: modify DB files

* docs: write readme.md

* docs: modify readme.md

* feat: consolidate MVVM pattern

* docs: write readme.md

* style: searchHistory and places cardviews

* style: modify recyclerviews

* feat: implement viewmodel and livedata

* style: modify placemodule

* feat: implement searchHistory

* feat: add search history animation

* feat: implementing search history click

* style: move xml ui string to strings.xml

* check

* delete useless variable

* modify code according to feedback

* move search history methods to repository

* modify README.md

* docs: write readme.md

* feat: make DTO and retrofitservice interface

* feat: implement api search

* style: long place name shortening

* refactor: move search api method to repository

* feat: generate map view methods

* docs: write readme.md

* feat: add mapview

* style: make search window of map activity

* feat: clicking search window to go search activity

* refactor: modify code according to first feedback

* refactor: move history methods to viewmodel

---------

Co-authored-by: MyStoryG <[email protected]>

* fix: merge rest things

* refactor: move places mutable livedata to viewmodel

* refactor: implement listadapter

* docs: write readme.md

* docs: modify readme.md

* feat: make addlabel method

* style: make map error xml

* feat: implementaion of save last position

* feat: make bottomsheet methods

* style: modify bottomsheet design

* refactor: modfify the method of switch activity

* fix: remove useless variable

---------

Co-authored-by: MyStoryG <[email protected]>
  • Loading branch information
settle54 and MyStoryG authored Jul 20, 2024
1 parent e5245dc commit 1f7e10d
Show file tree
Hide file tree
Showing 17 changed files with 482 additions and 93 deletions.
18 changes: 17 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,18 @@
# android-map-location
# 카테캠 4주차 과제

## 1단계 - 카카오맵 API 심화

### 기능 요구 사항

- 저장된 검색어를 선택하면 해당 검색어의 검색 결과가 표시된다.
- 검색 결과 목록 중 하나의 항목을 선택하면 해당 항목의 위치를 지도에 표시한다.
- 앱 종료 시 마지막 위치를 저장하여 다시 앱 실행 시 해당 위치로 포커스 한다.
- 카카오지도 onMapError() 호출 시 에러 화면을 보여준다.


### 프로그래밍 요구 사항

- BottomSheet를 사용한다.
- 카카오 API 사용을 위한 앱 키를 외부에 노출하지 않는다.
- 가능한 MVVM 아키텍처 패턴을 적용하도록 한다.
- 코드 컨벤션을 준수하며 프로그래밍한다.
4 changes: 3 additions & 1 deletion app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,9 @@ dependencies {
androidTestImplementation("androidx.test:rules:1.5.0")
androidTestImplementation("androidx.test.espresso:espresso-intents:3.5.1")



// https://developer.android.com/codelabs/android-preferences-datastore?hl=ko#4
implementation ("androidx.datastore:datastore-preferences:1.0.0") // prefs.getString() -> 동기 형태 : 개선필요
implementation ("com.kakao.sdk:v2-all:2.20.3")
implementation ("androidx.activity:activity-ktx:$activity_version")
implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version")
Expand Down
153 changes: 145 additions & 8 deletions app/src/main/java/campus/tech/kakao/map/MainActivity.kt
Original file line number Diff line number Diff line change
@@ -1,58 +1,195 @@
package campus.tech.kakao.map

import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.util.Log
import android.util.TypedValue
import android.view.View
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.cardview.widget.CardView
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
import campus.tech.kakao.map.databinding.ActivityMainBinding
import campus.tech.kakao.map.model.Place
import campus.tech.kakao.map.viewModel.MapRepository
import com.google.android.material.bottomsheet.BottomSheetBehavior
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.camera.CameraAnimation
import com.kakao.vectormap.camera.CameraUpdateFactory
import com.kakao.vectormap.label.Label
import com.kakao.vectormap.label.LabelOptions
import com.kakao.vectormap.label.LabelStyle
import com.kakao.vectormap.label.LabelStyles
import com.kakao.vectormap.label.Transition
import java.lang.Exception


class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
private lateinit var kakaoMap: KakaoMap
private lateinit var marker: Bitmap
private var label: Label? = null
private lateinit var styles: LabelStyles

private lateinit var bottomSheetBehavior: BottomSheetBehavior<ConstraintLayout>
private val bottomSheetLayout by lazy { findViewById<ConstraintLayout>(R.id.bottom_sheet_layout) }
private val bottomSheetName by lazy { findViewById<TextView>(R.id.name) }
private val bottomSheetAddress by lazy { findViewById<TextView>(R.id.address) }
private val bottomSheetCategory by lazy { findViewById<TextView>(R.id.category) }

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)

//KakaoMapSdk.init(this, "I'm nativeKey") // 오류확인

Log.d("onCreate", "")
val lastPos = MapRepository(this).getLastPos()
drawMap(lastPos)
initBottomSheet()

binding.searchInput.setOnClickListener {
val intent = Intent(this, SearchActivity::class.java)
startActivity(intent)
}

binding.searchButton.setOnClickListener {
val intent = Intent(this, SearchActivity::class.java)
startActivity(intent)
}
}

private fun drawMap(latLng: LatLng?) {
binding.mapView.start(object : MapLifeCycleCallback() {
override fun onMapDestroy() {
Log.d("KakaoMap", "카카오맵 종료")
}

override fun onMapError(e: Exception?) {
Log.e("KakaoMap", "카카오맵 인증실패", e)
setContentView(R.layout.map_error)
val errorMessage = findViewById<TextView>(R.id.errorMessage)
errorMessage.text = e?.message
}
}, object : KakaoMapReadyCallback() {
override fun onMapReady(p0: KakaoMap) {
Log.d("KakaoMap", "카카오맵 실행")
kakaoMap = p0
makeLabelStyle()
// addLabel(Place("dd", "xxx", "", "127.115587", "37.406960"))
}

override fun getPosition(): LatLng {
return latLng ?: return super.getPosition()
}
})
}

binding.searchInput.setOnClickListener {
val intent = Intent(this, SearchActivity::class.java)
startActivity(intent)
}
private fun addLabel(place: Place) {
val latLng = LatLng.from(place.latitude.toDouble(), place.longitude.toDouble())
moveCamera(latLng)
label = kakaoMap.labelManager!!.layer!!.addLabel(
LabelOptions.from(latLng)
.setStyles(styles).setTexts(place.name)
)
}

binding.searchButton.setOnClickListener {
val intent = Intent(this, SearchActivity::class.java)
startActivity(intent)
}
private fun moveCamera(latLng: LatLng) {
val cameraUpdate = CameraUpdateFactory.newCenterPosition(latLng)
Log.d("MainAct State", "Intent is: $intent")
Log.d("kakaomap", "moveCamera: $kakaoMap")
kakaoMap?.moveCamera(cameraUpdate, CameraAnimation.from(500, true, true))
}

private fun makeLabelStyle() {
vectorToBitmap(R.drawable.pin_drop_24px)

styles = LabelStyles.from(
"myLabel",
LabelStyle.from(marker)
.setTextStyles(32, Color.BLACK, 1, Color.GRAY)
.setZoomLevel(kakaoMap!!.minZoomLevel)
)
styles = kakaoMap.labelManager?.addLabelStyles(styles)!!
}

private fun vectorToBitmap(drawableId: Int) {
val drawable = ContextCompat.getDrawable(this, drawableId)
val bitmap = Bitmap.createBitmap(
drawable!!.intrinsicWidth,
drawable!!.intrinsicHeight,
Bitmap.Config.ARGB_8888
)
val canvas = Canvas(bitmap)
drawable.setBounds(0, 0, canvas.width, canvas.height)
drawable.draw(canvas)
marker = bitmap
}

private fun showBottomSheet(place: Place) {
bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
bottomSheetName.text = place.name
bottomSheetAddress.text = place.address
bottomSheetCategory.text = place.category
}

private fun initBottomSheet() {
bottomSheetBehavior = BottomSheetBehavior.from(bottomSheetLayout)
bottomSheetBehavior.addBottomSheetCallback(object :
BottomSheetBehavior.BottomSheetCallback() {
override fun onStateChanged(bottomSheet: View, newState: Int) {
binding.searchWindow.isInvisible = (newState < BottomSheetBehavior.STATE_COLLAPSED)
when (newState) {
BottomSheetBehavior.STATE_HIDDEN -> {
bottomSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED
}
}
}

override fun onSlide(p0: View, p1: Float) {
}
})
bottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
}

override fun onResume() {
super.onResume()
binding.mapView.resume()
Log.d("MainAct State", "Intent is: $intent")

}

override fun onPause() {
super.onPause()
binding.mapView.pause()
}

override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
intent?.let {
var place: Place?
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
place = intent.getParcelableExtra("place", Place::class.java)
} else {
place = intent.getParcelableExtra("place") as Place?
}
place?.let {
kakaoMap.labelManager!!.layer!!.remove(label)
addLabel(place)
showBottomSheet(place)
}
}
}
}
19 changes: 12 additions & 7 deletions app/src/main/java/campus/tech/kakao/map/PlacesAdapter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,42 @@ import campus.tech.kakao.map.model.Place
import campus.tech.kakao.map.databinding.PlaceModuleBinding

class PlacesAdapter(
private val onClick: (Int) -> Unit
private val onClick: (Place) -> Unit
) : RecyclerView.Adapter<PlacesAdapter.ViewHolder>() {

private var localList: List<Place> = emptyList()
private var placesList: List<Place> = emptyList()

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val binding = PlaceModuleBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return ViewHolder(binding)
}

override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(localList[position])
holder.bind(placesList[position])
}

override fun getItemCount(): Int {
return localList.size
return placesList.size
}

fun updateList(newList: List<Place>) {
localList = newList
placesList = newList
}

fun getItem(position: Int): Place {
return placesList[position]
}

fun getItemName(position: Int): String {
return localList[position].name
return placesList[position].name
}

inner class ViewHolder(private val binding: PlaceModuleBinding): RecyclerView.ViewHolder(binding.root) {

init {
binding.root.setOnClickListener {
onClick(bindingAdapterPosition)
onClick(placesList[bindingAdapterPosition])

}
}

Expand Down
Loading

0 comments on commit 1f7e10d

Please sign in to comment.