Google Maps Utility KML


적용 및 사용 방법 : https://developers.google.com/maps/documentation/android-api/utility/kml?hl=ko


1. 현재 공식 지원 중인 KML Utility는 베타 버전으로 일부 태그는 부분적으로 지원하거나 지원되지 않음


2. 1번의 이유로 Style 태그는 지원하지만 StyleMap 태그는 부분적으로 지원함 - 강조(Hightlight)는 지원안됨


3. KmlContainer는 하나의 Document 또는 Folder를 지칭함


4. 일반적으로 Style 관련 태그는 첫번째 Container에 포함되어 있음


5. Placemark의 style을 가져오기 위해서는 Style 태그가 포함된 Container에서 getStyle 함수를 통해 가져올 수 있음 


6. normal 상태와 highlight 상태를 가지는 StyleMap의 id는 불러오면 오류 발생


7. StyleMap id 뒤에 '-normal' 혹은 '-highlight'를 붙이면 getStyle 함수를 통해 데이터를 가져올 수 있음


8. layer에서 addLayerToMap 함수는 normal 상태의 style만 적용


9. addLayerToMap로 불러와도 색이 적용되지 않는 이유는 데이터에 내용이 누락됨 (이유는 알 수 없음)


* 이 외 style과 관련된 팁을 발견하면 추가 예정


* 이 팁들은 구글 내 지도 서비스에서 KML 내보내기를 통해 얻은 KML 파일을 기준으로 작성되었습니다.

by JamesY 2018. 1. 22. 19:38

Google Maps utility library란?

https://developers.google.com/maps/documentation/android-api/utility/?hl=ko


안드로이드에서 Google Maps을 사용하여 개발하다 보면 두 좌표 간 거리,  GeoJSON, KML 등 부족한 부분이 존재한다.


구글에서 이 부분을 메워줄 수 있는 공식 유틸리티 라이브러리를 제공한다.

GeoJSON 계층이 있는 지도

지도에 GeoJSON 가져오기

지형지물을 GeoJSON 형식으로 저장하고 이 유틸리티를 사용하여 지도 위의 계층으로 렌더링할 수 있습니다. addLayer()를 호출하여 지도에 GeoJSON 데이터를 추가합니다. addFeature()를 호출하고 GeoJsonFeature 객체에 전달하여 개별 지형지물을 추가할 수도 있습니다.

자세한 내용은 Google Maps Android GeoJSON 유틸리티에 관한 문서를 참조하세요.

KML 계층이 있는 지도

지도에 KML 가져오기

이 유틸리티를 사용하면 KML 객체를 지리적 셰이프로 변환하고 지도 위의 계층으로 렌더링할 수 있습니다. addLayerToMap()을 호출하여 지도에 계층을 추가합니다. Placemark, GroundOverlay, Document 또는 Folder에서 getProperties()를 호출하여 KML 객체의 속성에 액세스할 수 있습니다.

자세한 내용은 Google Maps Android KML 유틸리티에 관한 문서를 참조하세요.

열지도가 있는 지도

지도에 열지도 추가

열지도를 사용하면 뷰어가 지도에서 데이터 지점의 분포와 상대적 강도를 쉽게 이해할 수 있습니다. 열지도는 각 위치에 마커를 배치하는 대신 색상과 셰이프를 사용하여 데이터의 분포를 나타냅니다. HeatmapTileProvider를 생성하고 지도의 관심 지점을 나타내는 LatLng 객체 컬렉션에 전달합니다. 그런 다음 새 TileOverlay를 생성하여 열지도 타일 제공자에 전달하고, 지도에 타일 오버레이를 추가합니다.

자세한 내용은 Google Maps Android 열지도 유틸리티에 관한 문서를 참조하세요.

버블 아이콘이 있는 지도

버블 아이콘을 통해 마커 사용자 지정

IconGenerator를 추가하여 마커에 정보 조각을 표시합니다. 이 유틸리티는 마커 아이콘을 정보 창처럼 보이게 해서, 여기에 텍스트와 다른 콘텐츠를 담는 방법을 제공합니다. 정보 창은 한 번에 하나만 열 수 있지만 이 유틸리티는 하나 이상의 마커를 동시에 열 수 있다는 장점이 있습니다. 또한, 마커의 스타일을 지정하고, 마커 및/또는 콘텐츠의 방향을 변경하고, 마커의 배경 이미지/나인 패치를 변경할 수 있습니다.

클러스터형 마커가 있는 지도

마커 클러스터 관리

ClusterManager를 사용하면 다양한 확대/축소 수준에서 여러 개의 마커를 관리할 수 있습니다. 즉, 지도의 가독성을 해치지 않으면서도 지도에 많은 마커를 넣을 수 있습니다. 사용자가 높은 확대/축소 수준에서 지도를 보면, 개별 마커가 지도에 나타납니다. 사용자가 낮은 확대/축소 수준으로 축소하면, 마커가 클러스터로 모여서 지도를 보기 쉽게 해줍니다.

자세한 내용은 Google Maps Android 마커 클러스터링 유틸리티를 참조하세요.

인코딩된 폴리라인이 있는 지도

폴리라인 인코딩 및 디코딩

PolyUtil은 인코딩된 폴리라인과 폴리곤을 경도/위도 좌표로 변환하거나 그 반대로 변환할 때 유용합니다.

Google 지도에서 폴리라인이나 폴리곤을 정의하는 경도와 위도 좌표는 인코딩된 문자열로 저장됩니다. 폴리라인 인코딩에 대한 자세한 설명을 참조하세요. Google Maps Directions API와 같은 Google API의 응답에서 이 인코딩된 문자열을 수신할 수 있습니다.

Google Maps Android API 유틸리티 라이브러리에서 PolyUtil을 사용하여 일련의 경도/위도 좌표('LatLngs')를 인코딩된 경로 문자열로 인코딩하고, 인코딩된 경로 문자열을 일련의 LatLngs로 디코딩/인코딩할 수 있습니다. 이는 Google Maps API 웹 서비스와의 상호운용성을 보장합니다.

지도 상에서 두 지점 간의 거리 계산

구면 기하학을 통해 거리, 영역 및 방향 계산

SphericalUtil의 구면 기하학 유틸리티를 사용하여 경도와 위도를 기반으로 거리, 영역, 방향을 계산할 수 있습니다. 다음은 유틸리티에서 사용할 수 있는 몇 가지 메서드입니다.

  • computeDistanceBetween() – 두 개의 위도/경도 좌표 사이의 거리를 미터 단위로 반환합니다.
  • computeHeading() – 두 개의 위도/경도 좌표 사이의 베어링을 도 단위로 반환합니다.
  • computeArea() – 지구 위의 닫힌 경로의 영역을 제곱미터 단위로 반환합니다.
  • interpolate() – 주어진 두 지점 사이의 거리에서 지정된 부분에 있는 지점의 경도/위도 좌표를 반환합니다. 예를 들어, 이 메서드를 사용하여 두 지점 사이의 마커를 애니메이트할 수 있습니다.

유틸리티에 포함된 메서드의 전체 목록은 참조 문서를 참조하세요.


GitHub : https://github.com/googlemaps/android-maps-utils

by JamesY 2018. 1. 15. 19:19

Constraint Layout을 이용하여 간단한 이동 애니메이션을 구현할 수 있다.


먼저 Constraint Layout을 어떤식으로 사용하는지 알아야 하기 때문에 모를 경우 배우고 난 뒤 읽는 것을 추천


결과물





1. Floating action button을 Constraint Layout에 넣기

<android.support.constraint.ConstraintLayout
android:id="@+id/menu_layout"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="bottom|end" >

<android.support.design.widget.FloatingActionButton
android:id="@+id/fab1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/fab_margin"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:srcCompat="@android:drawable/ic_dialog_alert"
app:fabSize="mini" />

<android.support.design.widget.FloatingActionButton
android:id="@+id/fab2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/fab_margin"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:srcCompat="@android:drawable/ic_dialog_info"
app:fabSize="mini" />

<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/fab_margin"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:srcCompat="@android:drawable/ic_dialog_email" />

</android.support.constraint.ConstraintLayout>

fab은 메뉴 버튼, fab1과 fab2는 fab을 누를 시 나오는 항목들


2. fab 버튼 이벤트 구현

class MainActivity : AppCompatActivity() {

private var isMenuCollapsed = true

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
setSupportActionBar(toolbar)

fab.setOnClickListener { view ->
val constraintSet = ConstraintSet()
constraintSet.clone(menu_layout)

if(isMenuCollapsed) {
// Set fab1's position to top of fab
constraintSet.connect(fab1.id, ConstraintSet.BOTTOM, fab.id, ConstraintSet.TOP)
// Set fab2's position to top of fab1
constraintSet.connect(fab2.id, ConstraintSet.BOTTOM, fab1.id, ConstraintSet.TOP)
}
else {
// Set fab1's position back to bottom
constraintSet.connect(fab1.id, ConstraintSet.BOTTOM, fab.id, ConstraintSet.BOTTOM)
// Set fab2's position back to bottom
constraintSet.connect(fab2.id, ConstraintSet.BOTTOM, fab.id, ConstraintSet.BOTTOM)
}
val transition = AutoTransition()
transition.duration = 300
transition.interpolator = AccelerateDecelerateInterpolator()

TransitionManager.beginDelayedTransition(menu_layout, transition)
constraintSet.applyTo(menu_layout)

isMenuCollapsed = !isMenuCollapsed
}
}

override fun onCreateOptionsMenu(menu: Menu): Boolean {
// Inflate the menu; this adds items to the action bar if it is present.
menuInflater.inflate(R.menu.menu_main, menu)
return true
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
return when (item.itemId) {
R.id.action_settings -> true
else -> super.onOptionsItemSelected(item)
}
}
}


이 방법은 menu_layout의 클론(constraintSet)을 만들고 fab1과 fab2의 새로운 위치를 지정 해주고 Transition을 한다. 결과적으로는 두 개의 menu_layout을 통해 애니메이션을 구현한 것이다.


Constraint를 잘 활용하면 예제처럼 아래서 위로 가는 것뿐만 아니라 오른쪽에서 왼쪽 또는 대각선 까지 다양한 방향 전환이 가능하다.


GitHub : https://github.com/Hot6ix/FloatingActionButton

참조 : https://robinhood.engineering/beautiful-animations-using-android-constraintlayout-eee5b72ecae3

'Android > Kotlin' 카테고리의 다른 글

커스텀 리스트뷰 ( Custom ListView)  (0) 2017.12.21
Volley를 이용한 간단한 네트워크 통신  (0) 2017.12.21
by JamesY 2018. 1. 9. 23:45
| 1 2 3 4 5 6 7 8 |