일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- 막내의막무가내 플러터 flutter
- 프래그먼트
- 막내의막무가내 안드로이드 코틀린
- Fragment
- 프로그래머스 알고리즘
- 막내의막무가내 SQL
- 부스트코스에이스
- flutter network call
- 주택가 잠실새내
- 막내의막무가내 프로그래밍
- 부스트코스
- 막내의막무가내 rxjava
- 막내의막무가내
- 안드로이드 sunflower
- 막내의 막무가내 알고리즘
- 막내의막무가내 코볼 COBOL
- 2022년 6월 일상
- 안드로이드
- 막내의막무가내 안드로이드
- 막내의막무가내 코틀린 안드로이드
- 막내의막무가내 일상
- 막내의막무가내 플러터
- 막내의 막무가내
- 막내의막무가내 알고리즘
- 막내의막무가내 안드로이드 에러 해결
- 주엽역 생활맥주
- 막내의막무가내 코틀린
- 안드로이드 Sunflower 스터디
- 막무가내
- 막내의막무가내 목표 및 회고
- Today
- Total
막내의 막무가내 프로그래밍 & 일상
[안드로이드] 카카오맵 API 코드 기록 본문
[2021-04-18 업데이트]
코드 물어보시는 분들이 많아 프로젝트 공유합니다.
https://github.com/mtjin/LandKorea_AndroidApp
mtjin/LandKorea_AndroidApp
잡코리아 땅버전앱. Contribute to mtjin/LandKorea_AndroidApp development by creating an account on GitHub.
github.com
참고사이트: 저는 카카오맵 공식문서에 대해 자세한 설명을 담아서 포스팅하지 않고 코드위주로 기록해놨습니다. 카카오맵 API 문서는 매우 잘되어있으므로 공식문서를 보고 하는것을 추천드립니다. 하다가 안되는게 있으면 이 포스팅의 코드기록을 참고하시거나 궁금사항을 여쭤보시면 감사하겠습니다 :) (아마 지도 혹은 기본 좌표 세팅, 카카오맵 콜백함수, Rest API와의 Retrofit2 통신, 커스텀 좌표 등을 참고하실거라 예상합니다.)
카카오맵 기본 세팅 가이드, 기본 기능 제공
http://apis.map.kakao.com/android/guide/
카카오맵 함수 API 문서
http://apis.map.kakao.com/android/documentation/
카카오맵 REST API 문서 (단순 SDK 이용이 아닌 Retrofit2 통신이 필요한 부분들 ex. 장소 카테고리, 이름, 주소로 검색 )
developers.kakao.com/docs/latest/ko/local/dev-guide
Kakao Developers
카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.
developers.kakao.com
카카오맵 API 사용코드입니다.
[참고 아닌 핑계?]
기능만 구현되게 급하게 짜서 코드가 많이 더럽습니다. ㅠㅠ 그리고 MVC와 다중 통신을 ApiInterface로 콜백의 연속으로 구현했기에 더러워염 ㅠㅠ
하지만 저는 알아볼 수는 있어서 나중에 또 카카오맵 API를 사용했을 때 기억을 상기시킬려고 코드를 올립니다.
길찾기, 카테고리검색, 특정 좌표에서 1km 내의 주변환경 검색, 장소검색, 네비게이션, 마커, circle, pollItem, tracking mode 등 카카오맵API 에서 제공하는 대부분의 기능을 담았습니다.
검색같은 경우는 카카오톡 Local REST API와 통신을 해야하므로 retrofit2를 사용하였다.
(나중에 시간이 되면 코드를 정리해서 올리도록 하겠습니다.)
[MapActivity]
package com.mtjin.mapogreen.activities;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.crowdfire.cfalertdialog.CFAlertDialog;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.mtjin.mapogreen.R;
import com.mtjin.mapogreen.adapter.LocationAdapter;
import com.mtjin.mapogreen.api.ApiClient;
import com.mtjin.mapogreen.api.ApiInterface;
import com.mtjin.mapogreen.model.category_search.Document;
import com.mtjin.mapogreen.model.category_search.CategoryResult;
import com.mtjin.mapogreen.utils.BusProvider;
import com.mtjin.mapogreen.utils.IntentKey;
import com.shashank.sony.fancytoastlib.FancyToast;
import com.squareup.otto.Bus;
import com.squareup.otto.Subscribe;
import net.daum.mf.map.api.MapCircle;
import net.daum.mf.map.api.MapPOIItem;
import net.daum.mf.map.api.MapPoint;
import net.daum.mf.map.api.MapView;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class MapActivity extends AppCompatActivity implements MapView.MapViewEventListener, MapView.POIItemEventListener, MapView.OpenAPIKeyAuthenticationResultListener, View.OnClickListener, MapView.CurrentLocationEventListener {
final static String TAG = "MapTAG";
//xml
MapView mMapView;
ViewGroup mMapViewContainer;
EditText mSearchEdit;
private Animation fab_open, fab_close;
private Boolean isFabOpen = false;
private FloatingActionButton fab, fab1, fab2, fab3, searchDetailFab, stopTrackingFab;
RelativeLayout mLoaderLayout;
RecyclerView recyclerView;
//value
MapPoint currentMapPoint;
private double mCurrentLng; //Long = X, Lat = Yㅌ
private double mCurrentLat;
private double mSearchLng = -1;
private double mSearchLat = -1;
private String mSearchName;
boolean isTrackingMode = false; //트래킹 모드인지 (3번째 버튼 현재위치 추적 눌렀을 경우 true되고 stop 버튼 누르면 false로 된다)
Bus bus = BusProvider.getInstance();
ArrayList<Document> bigMartList = new ArrayList<>(); //대형마트 MT1
ArrayList<Document> gs24List = new ArrayList<>(); //편의점 CS2
ArrayList<Document> schoolList = new ArrayList<>(); //학교 SC4
ArrayList<Document> academyList = new ArrayList<>(); //학원 AC5
ArrayList<Document> subwayList = new ArrayList<>(); //지하철 SW8
ArrayList<Document> bankList = new ArrayList<>(); //은행 BK9
ArrayList<Document> hospitalList = new ArrayList<>(); //병원 HP8
ArrayList<Document> pharmacyList = new ArrayList<>(); //약국 PM9
ArrayList<Document> cafeList = new ArrayList<>(); //카페
ArrayList<Document> documentArrayList = new ArrayList<>(); //지역명 검색 결과 리스트
MapPOIItem searchMarker = new MapPOIItem();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
setContentView(R.layout.activity_map);
bus.register(this); //정류소 등록
initView();
}
private void initView() {
//binding
mSearchEdit = findViewById(R.id.map_et_search);
fab_open = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.fab_open);
fab_close = AnimationUtils.loadAnimation(getApplicationContext(), R.anim.fab_close);
fab = findViewById(R.id.fab);
fab1 = findViewById(R.id.fab1);
fab2 = findViewById(R.id.fab2);
fab3 = findViewById(R.id.fab3);
searchDetailFab = findViewById(R.id.fab_detail);
stopTrackingFab = findViewById(R.id.fab_stop_tracking);
mLoaderLayout = findViewById(R.id.loaderLayout);
mMapView = new MapView(this);
mMapViewContainer = findViewById(R.id.map_mv_mapcontainer);
mMapViewContainer.addView(mMapView);
recyclerView = findViewById(R.id.map_recyclerview);
LocationAdapter locationAdapter = new LocationAdapter(documentArrayList, getApplicationContext(), mSearchEdit, recyclerView);
LinearLayoutManager layoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); //레이아웃매니저 생성
recyclerView.addItemDecoration(new DividerItemDecoration(getApplicationContext(), DividerItemDecoration.VERTICAL)); //아래구분선 세팅
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(locationAdapter);
//맵 리스너
mMapView.setMapViewEventListener(this); // this에 MapView.MapViewEventListener 구현.
mMapView.setPOIItemEventListener(this);
mMapView.setOpenAPIKeyAuthenticationResultListener(this);
//버튼리스너
fab.setOnClickListener(this);
fab1.setOnClickListener(this);
fab2.setOnClickListener(this);
fab3.setOnClickListener(this);
searchDetailFab.setOnClickListener(this);
stopTrackingFab.setOnClickListener(this);
Toast.makeText(this, "맵을 로딩중입니다", Toast.LENGTH_SHORT).show();
//맵 리스너 (현재위치 업데이트)
mMapView.setCurrentLocationEventListener(this);
//setCurrentLocationTrackingMode (지도랑 현재위치 좌표 찍어주고 따라다닌다.)
mMapView.setCurrentLocationTrackingMode(MapView.CurrentLocationTrackingMode.TrackingModeOnWithoutHeading);
mLoaderLayout.setVisibility(View.VISIBLE);
// editText 검색 텍스처이벤트
mSearchEdit.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {
// 입력하기 전에
recyclerView.setVisibility(View.VISIBLE);
}
@Override
public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
if (charSequence.length() >= 1) {
// if (SystemClock.elapsedRealtime() - mLastClickTime < 500) {
documentArrayList.clear();
locationAdapter.clear();
locationAdapter.notifyDataSetChanged();
ApiInterface apiInterface = ApiClient.getApiClient().create(ApiInterface.class);
Call<CategoryResult> call = apiInterface.getSearchLocation(getString(R.string.restapi_key), charSequence.toString(), 15);
call.enqueue(new Callback<CategoryResult>() {
@Override
public void onResponse(@NotNull Call<CategoryResult> call, @NotNull Response<CategoryResult> response) {
if (response.isSuccessful()) {
assert response.body() != null;
for (Document document : response.body().getDocuments()) {
locationAdapter.addItem(document);
}
locationAdapter.notifyDataSetChanged();
}
}
@Override
public void onFailure(@NotNull Call<CategoryResult> call, @NotNull Throwable t) {
}
});
//}
//mLastClickTime = SystemClock.elapsedRealtime();
} else {
if (charSequence.length() <= 0) {
recyclerView.setVisibility(View.GONE);
}
}
}
@Override
public void afterTextChanged(Editable editable) {
// 입력이 끝났을 때
}
});
mSearchEdit.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View view, boolean hasFocus) {
if (hasFocus) {
} else {
recyclerView.setVisibility(View.GONE);
}
}
});
mSearchEdit.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
FancyToast.makeText(getApplicationContext(), "검색리스트에서 장소를 선택해주세요", FancyToast.LENGTH_SHORT, FancyToast.INFO, true).show();
}
});
}
@Override
public void onClick(View v) {
int id = v.getId();
switch (id) {
case R.id.fab:
FancyToast.makeText(this, "1번 버튼: 검색좌표 기준으로 1km 검색" +
"\n2번 버튼: 현재위치 기준으로 주변환경 검색" +
"\n3번 버튼: 현재위치 추적 및 업데이트", FancyToast.LENGTH_SHORT, FancyToast.INFO, true).show();
anim();
break;
case R.id.fab1: //아래버튼에서부터 1~3임
FancyToast.makeText(this, "현재위치 추적 시작", FancyToast.LENGTH_SHORT, FancyToast.SUCCESS, true).show();
searchDetailFab.setVisibility(View.GONE);
mLoaderLayout.setVisibility(View.VISIBLE);
isTrackingMode = true;
mMapView.setCurrentLocationTrackingMode(MapView.CurrentLocationTrackingMode.TrackingModeOnWithHeading);
anim();
stopTrackingFab.setVisibility(View.VISIBLE);
mLoaderLayout.setVisibility(View.GONE);
break;
case R.id.fab2:
isTrackingMode = false;
FancyToast.makeText(this, "현재위치기준 1km 검색 시작", FancyToast.LENGTH_SHORT, FancyToast.SUCCESS, true).show();
stopTrackingFab.setVisibility(View.GONE);
mLoaderLayout.setVisibility(View.VISIBLE);
anim();
//현재 위치 기준으로 1km 검색
mMapView.removeAllPOIItems();
mMapView.removeAllCircles();
requestSearchLocal(mCurrentLng, mCurrentLat);
mMapView.setCurrentLocationTrackingMode(MapView.CurrentLocationTrackingMode.TrackingModeOnWithoutHeading);
break;
case R.id.fab3:
isTrackingMode = false;
mMapView.setCurrentLocationTrackingMode(MapView.CurrentLocationTrackingMode.TrackingModeOff);
mLoaderLayout.setVisibility(View.VISIBLE);
anim();
if (mSearchLat != -1 && mSearchLng != -1) {
mMapView.removeAllPOIItems();
mMapView.removeAllCircles();
mMapView.addPOIItem(searchMarker);
requestSearchLocal(mSearchLng, mSearchLat);
} else {
FancyToast.makeText(this, "검색 먼저 해주세요", FancyToast.LENGTH_SHORT, FancyToast.ERROR, true).show();
}
mLoaderLayout.setVisibility(View.GONE);
break;
case R.id.fab_detail:
FancyToast.makeText(this, "검색결과 상세보기", FancyToast.LENGTH_SHORT, FancyToast.SUCCESS, true).show();
Intent detailIntent = new Intent(MapActivity.this, MapSearchDetailActivity.class);
detailIntent.putParcelableArrayListExtra(IntentKey.CATEGOTY_SEARCH_MODEL_EXTRA1, bigMartList);
detailIntent.putParcelableArrayListExtra(IntentKey.CATEGOTY_SEARCH_MODEL_EXTRA2, gs24List);
detailIntent.putParcelableArrayListExtra(IntentKey.CATEGOTY_SEARCH_MODEL_EXTRA3, schoolList);
detailIntent.putParcelableArrayListExtra(IntentKey.CATEGOTY_SEARCH_MODEL_EXTRA4, academyList);
detailIntent.putParcelableArrayListExtra(IntentKey.CATEGOTY_SEARCH_MODEL_EXTRA5, subwayList);
detailIntent.putParcelableArrayListExtra(IntentKey.CATEGOTY_SEARCH_MODEL_EXTRA6, bankList);
detailIntent.putParcelableArrayListExtra(IntentKey.CATEGOTY_SEARCH_MODEL_EXTRA7, hospitalList);
detailIntent.putParcelableArrayListExtra(IntentKey.CATEGOTY_SEARCH_MODEL_EXTRA8, pharmacyList);
detailIntent.putParcelableArrayListExtra(IntentKey.CATEGOTY_SEARCH_MODEL_EXTRA9, cafeList);
overridePendingTransition(R.anim.fade_in_splash, R.anim.fade_out_splash);
startActivity(detailIntent);
Log.d(TAG, "fab_detail");
break;
case R.id.fab_stop_tracking:
isTrackingMode = false;
mMapView.setCurrentLocationTrackingMode(MapView.CurrentLocationTrackingMode.TrackingModeOff);
stopTrackingFab.setVisibility(View.GONE);
FancyToast.makeText(this, "현재위치 추적 종료", FancyToast.LENGTH_SHORT, FancyToast.SUCCESS, true).show();
break;
}
}
private void requestSearchLocal(double x, double y) {
bigMartList.clear();
gs24List.clear();
schoolList.clear();
academyList.clear();
subwayList.clear();
bankList.clear();
hospitalList.clear();
pharmacyList.clear();
cafeList.clear();
ApiInterface apiInterface = ApiClient.getApiClient().create(ApiInterface.class);
Call<CategoryResult> call = apiInterface.getSearchCategory(getString(R.string.restapi_key), "MT1", x + "", y + "", 1000);
call.enqueue(new Callback<CategoryResult>() {
@Override
public void onResponse(@NotNull Call<CategoryResult> call, @NotNull Response<CategoryResult> response) {
if (response.isSuccessful()) {
assert response.body() != null;
if (response.body().getDocuments() != null) {
Log.d(TAG, "bigMartList Success");
bigMartList.addAll(response.body().getDocuments());
}
call = apiInterface.getSearchCategory(getString(R.string.restapi_key), "CS2", x + "", y + "", 1000);
call.enqueue(new Callback<CategoryResult>() {
@Override
public void onResponse(@NotNull Call<CategoryResult> call, @NotNull Response<CategoryResult> response) {
if (response.isSuccessful()) {
assert response.body() != null;
Log.d(TAG, "gs24List Success");
gs24List.addAll(response.body().getDocuments());
call = apiInterface.getSearchCategory(getString(R.string.restapi_key), "SC4", x + "", y + "", 1000);
call.enqueue(new Callback<CategoryResult>() {
@Override
public void onResponse(@NotNull Call<CategoryResult> call, @NotNull Response<CategoryResult> response) {
if (response.isSuccessful()) {
assert response.body() != null;
Log.d(TAG, "schoolList Success");
schoolList.addAll(response.body().getDocuments());
call = apiInterface.getSearchCategory(getString(R.string.restapi_key), "AC5", x + "", y + "", 1000);
call.enqueue(new Callback<CategoryResult>() {
@Override
public void onResponse(@NotNull Call<CategoryResult> call, @NotNull Response<CategoryResult> response) {
if (response.isSuccessful()) {
assert response.body() != null;
Log.d(TAG, "academyList Success");
academyList.addAll(response.body().getDocuments());
call = apiInterface.getSearchCategory(getString(R.string.restapi_key), "SW8", x + "", y + "", 1000);
call.enqueue(new Callback<CategoryResult>() {
@Override
public void onResponse(@NotNull Call<CategoryResult> call, @NotNull Response<CategoryResult> response) {
if (response.isSuccessful()) {
assert response.body() != null;
Log.d(TAG, "subwayList Success");
subwayList.addAll(response.body().getDocuments());
call = apiInterface.getSearchCategory(getString(R.string.restapi_key), "BK9", x + "", y + "", 1000);
call.enqueue(new Callback<CategoryResult>() {
@Override
public void onResponse(@NotNull Call<CategoryResult> call, @NotNull Response<CategoryResult> response) {
if (response.isSuccessful()) {
assert response.body() != null;
Log.d(TAG, "bankList Success");
bankList.addAll(response.body().getDocuments());
call = apiInterface.getSearchCategory(getString(R.string.restapi_key), "HP8", x + "", y + "", 1000);
call.enqueue(new Callback<CategoryResult>() {
@Override
public void onResponse(@NotNull Call<CategoryResult> call, @NotNull Response<CategoryResult> response) {
if (response.isSuccessful()) {
assert response.body() != null;
Log.d(TAG, "hospitalList Success");
hospitalList.addAll(response.body().getDocuments());
call = apiInterface.getSearchCategory(getString(R.string.restapi_key), "PM9", x + "", y + "", 1000);
call.enqueue(new Callback<CategoryResult>() {
@Override
public void onResponse(@NotNull Call<CategoryResult> call, @NotNull Response<CategoryResult> response) {
if (response.isSuccessful()) {
assert response.body() != null;
Log.d(TAG, "pharmacyList Success");
pharmacyList.addAll(response.body().getDocuments());
call = apiInterface.getSearchCategory(getString(R.string.restapi_key), "CE7", x + "", y + "", 1000);
call.enqueue(new Callback<CategoryResult>() {
@Override
public void onResponse(@NotNull Call<CategoryResult> call, @NotNull Response<CategoryResult> response) {
if (response.isSuccessful()) {
assert response.body() != null;
Log.d(TAG, "cafeList Success");
cafeList.addAll(response.body().getDocuments());
//모두 통신 성공 시 circle 생성
MapCircle circle1 = new MapCircle(
MapPoint.mapPointWithGeoCoord(y, x), // center
1000, // radius
Color.argb(128, 255, 0, 0), // strokeColor
Color.argb(128, 0, 255, 0) // fillColor
);
circle1.setTag(5678);
mMapView.addCircle(circle1);
Log.d("SIZE1", bigMartList.size() + "");
Log.d("SIZE2", gs24List.size() + "");
Log.d("SIZE3", schoolList.size() + "");
Log.d("SIZE4", academyList.size() + "");
Log.d("SIZE5", subwayList.size() + "");
Log.d("SIZE6", bankList.size() + "");
//마커 생성
int tagNum = 10;
for (Document document : bigMartList) {
MapPOIItem marker = new MapPOIItem();
marker.setItemName(document.getPlaceName());
marker.setTag(tagNum++);
double x = Double.parseDouble(document.getY());
double y = Double.parseDouble(document.getX());
//카카오맵은 참고로 new MapPoint()로 생성못함. 좌표기준이 여러개라 이렇게 메소드로 생성해야함
MapPoint mapPoint = MapPoint.mapPointWithGeoCoord(x, y);
marker.setMapPoint(mapPoint);
marker.setMarkerType(MapPOIItem.MarkerType.CustomImage); // 마커타입을 커스텀 마커로 지정.
marker.setCustomImageResourceId(R.drawable.ic_big_mart_marker); // 마커 이미지.
marker.setCustomImageAutoscale(false); // hdpi, xhdpi 등 안드로이드 플랫폼의 스케일을 사용할 경우 지도 라이브러리의 스케일 기능을 꺼줌.
marker.setCustomImageAnchor(0.5f, 1.0f); // 마커 이미지중 기준이 되는 위치(앵커포인트) 지정 - 마커 이미지 좌측 상단 기준 x(0.0f ~ 1.0f), y(0.0f ~ 1.0f) 값.
mMapView.addPOIItem(marker);
}
for (Document document : gs24List) {
MapPOIItem marker = new MapPOIItem();
marker.setItemName(document.getPlaceName());
marker.setTag(tagNum++);
double x = Double.parseDouble(document.getY());
double y = Double.parseDouble(document.getX());
//카카오맵은 참고로 new MapPoint()로 생성못함. 좌표기준이 여러개라 이렇게 메소드로 생성해야함
MapPoint mapPoint = MapPoint.mapPointWithGeoCoord(x, y);
marker.setMapPoint(mapPoint);
marker.setMarkerType(MapPOIItem.MarkerType.CustomImage); // 마커타입을 커스텀 마커로 지정.
marker.setCustomImageResourceId(R.drawable.ic_24_mart_marker); // 마커 이미지.
marker.setCustomImageAutoscale(false); // hdpi, xhdpi 등 안드로이드 플랫폼의 스케일을 사용할 경우 지도 라이브러리의 스케일 기능을 꺼줌.
marker.setCustomImageAnchor(0.5f, 1.0f);
mMapView.addPOIItem(marker);
}
for (Document document : schoolList) {
MapPOIItem marker = new MapPOIItem();
marker.setItemName(document.getPlaceName());
marker.setTag(tagNum++);
double x = Double.parseDouble(document.getY());
double y = Double.parseDouble(document.getX());
//카카오맵은 참고로 new MapPoint()로 생성못함. 좌표기준이 여러개라 이렇게 메소드로 생성해야함
MapPoint mapPoint = MapPoint.mapPointWithGeoCoord(x, y);
marker.setMapPoint(mapPoint);
marker.setMarkerType(MapPOIItem.MarkerType.CustomImage); // 마커타입을 커스텀 마커로 지정.
marker.setCustomImageResourceId(R.drawable.ic_school_marker); // 마커 이미지.
marker.setCustomImageAutoscale(false); // hdpi, xhdpi 등 안드로이드 플랫폼의 스케일을 사용할 경우 지도 라이브러리의 스케일 기능을 꺼줌.
marker.setCustomImageAnchor(0.5f, 1.0f);
mMapView.addPOIItem(marker);
}
for (Document document : academyList) {
MapPOIItem marker = new MapPOIItem();
marker.setItemName(document.getPlaceName());
marker.setTag(tagNum++);
double x = Double.parseDouble(document.getY());
double y = Double.parseDouble(document.getX());
//카카오맵은 참고로 new MapPoint()로 생성못함. 좌표기준이 여러개라 이렇게 메소드로 생성해야함
MapPoint mapPoint = MapPoint.mapPointWithGeoCoord(x, y);
marker.setMapPoint(mapPoint);
marker.setMarkerType(MapPOIItem.MarkerType.CustomImage); // 마커타입을 커스텀 마커로 지정.
marker.setCustomImageResourceId(R.drawable.ic_academy_marker); // 마커 이미지.
marker.setCustomImageAutoscale(false); // hdpi, xhdpi 등 안드로이드 플랫폼의 스케일을 사용할 경우 지도 라이브러리의 스케일 기능을 꺼줌.
marker.setCustomImageAnchor(0.5f, 1.0f);
mMapView.addPOIItem(marker);
}
for (Document document : subwayList) {
MapPOIItem marker = new MapPOIItem();
marker.setItemName(document.getPlaceName());
marker.setTag(tagNum++);
double x = Double.parseDouble(document.getY());
double y = Double.parseDouble(document.getX());
//카카오맵은 참고로 new MapPoint()로 생성못함. 좌표기준이 여러개라 이렇게 메소드로 생성해야함
MapPoint mapPoint = MapPoint.mapPointWithGeoCoord(x, y);
marker.setMapPoint(mapPoint);
marker.setMarkerType(MapPOIItem.MarkerType.CustomImage); // 마커타입을 커스텀 마커로 지정.
marker.setCustomImageResourceId(R.drawable.ic_subway_marker); // 마커 이미지.
marker.setCustomImageAutoscale(false); // hdpi, xhdpi 등 안드로이드 플랫폼의 스케일을 사용할 경우 지도 라이브러리의 스케일 기능을 꺼줌.
marker.setCustomImageAnchor(0.5f, 1.0f);
mMapView.addPOIItem(marker);
}
for (Document document : bankList) {
MapPOIItem marker = new MapPOIItem();
marker.setItemName(document.getPlaceName());
marker.setTag(tagNum++);
double x = Double.parseDouble(document.getY());
double y = Double.parseDouble(document.getX());
//카카오맵은 참고로 new MapPoint()로 생성못함. 좌표기준이 여러개라 이렇게 메소드로 생성해야함
MapPoint mapPoint = MapPoint.mapPointWithGeoCoord(x, y);
marker.setMapPoint(mapPoint);
marker.setMarkerType(MapPOIItem.MarkerType.CustomImage); // 마커타입을 커스텀 마커로 지정.
marker.setCustomImageResourceId(R.drawable.ic_bank_marker); // 마커 이미지.
marker.setCustomImageAutoscale(false); // hdpi, xhdpi 등 안드로이드 플랫폼의 스케일을 사용할 경우 지도 라이브러리의 스케일 기능을 꺼줌.
marker.setCustomImageAnchor(0.5f, 1.0f);
mMapView.addPOIItem(marker);
}
for (Document document : hospitalList) {
MapPOIItem marker = new MapPOIItem();
marker.setItemName(document.getPlaceName());
marker.setTag(tagNum++);
double x = Double.parseDouble(document.getY());
double y = Double.parseDouble(document.getX());
//카카오맵은 참고로 new MapPoint()로 생성못함. 좌표기준이 여러개라 이렇게 메소드로 생성해야함
MapPoint mapPoint = MapPoint.mapPointWithGeoCoord(x, y);
marker.setMapPoint(mapPoint);
marker.setMarkerType(MapPOIItem.MarkerType.CustomImage); // 마커타입을 커스텀 마커로 지정.
marker.setCustomImageResourceId(R.drawable.ic_hospital_marker); // 마커 이미지.
marker.setCustomImageAutoscale(false); // hdpi, xhdpi 등 안드로이드 플랫폼의 스케일을 사용할 경우 지도 라이브러리의 스케일 기능을 꺼줌.
marker.setCustomImageAnchor(0.5f, 1.0f);
mMapView.addPOIItem(marker);
}
for (Document document : pharmacyList) {
MapPOIItem marker = new MapPOIItem();
marker.setItemName(document.getPlaceName());
marker.setTag(tagNum++);
double x = Double.parseDouble(document.getY());
double y = Double.parseDouble(document.getX());
//카카오맵은 참고로 new MapPoint()로 생성못함. 좌표기준이 여러개라 이렇게 메소드로 생성해야함
MapPoint mapPoint = MapPoint.mapPointWithGeoCoord(x, y);
marker.setMapPoint(mapPoint);
marker.setMarkerType(MapPOIItem.MarkerType.CustomImage); // 마커타입을 커스텀 마커로 지정.
marker.setCustomImageResourceId(R.drawable.ic_pharmacy_marker); // 마커 이미지.
marker.setCustomImageAutoscale(false); // hdpi, xhdpi 등 안드로이드 플랫폼의 스케일을 사용할 경우 지도 라이브러리의 스케일 기능을 꺼줌.
marker.setCustomImageAnchor(0.5f, 1.0f);
mMapView.addPOIItem(marker);
//자세히보기 fab 버튼 보이게
mLoaderLayout.setVisibility(View.GONE);
searchDetailFab.setVisibility(View.VISIBLE);
}
for (Document document : cafeList) {
MapPOIItem marker = new MapPOIItem();
marker.setItemName(document.getPlaceName());
marker.setTag(tagNum++);
double x = Double.parseDouble(document.getY());
double y = Double.parseDouble(document.getX());
//카카오맵은 참고로 new MapPoint()로 생성못함. 좌표기준이 여러개라 이렇게 메소드로 생성해야함
MapPoint mapPoint = MapPoint.mapPointWithGeoCoord(x, y);
marker.setMapPoint(mapPoint);
marker.setMarkerType(MapPOIItem.MarkerType.CustomImage); // 마커타입을 커스텀 마커로 지정.
marker.setCustomImageResourceId(R.drawable.ic_cafe_marker); // 마커 이미지.
marker.setCustomImageAutoscale(false); // hdpi, xhdpi 등 안드로이드 플랫폼의 스케일을 사용할 경우 지도 라이브러리의 스케일 기능을 꺼줌.
marker.setCustomImageAnchor(0.5f, 1.0f);
mMapView.addPOIItem(marker);
//자세히보기 fab 버튼 보이게
mLoaderLayout.setVisibility(View.GONE);
searchDetailFab.setVisibility(View.VISIBLE);
}
}
}
@Override
public void onFailure(@NotNull Call<CategoryResult> call, @NotNull Throwable t) {
}
});
}
}
@Override
public void onFailure(@NotNull Call<CategoryResult> call, Throwable t) {
}
});
}
}
@Override
public void onFailure(@NotNull Call<CategoryResult> call, @NotNull Throwable t) {
}
});
}
}
@Override
public void onFailure(@NotNull Call<CategoryResult> call, @NotNull Throwable t) {
}
});
}
}
@Override
public void onFailure(@NotNull Call<CategoryResult> call, @NotNull Throwable t) {
}
});
}
}
@Override
public void onFailure(@NotNull Call<CategoryResult> call, @NotNull Throwable t) {
}
});
}
}
@Override
public void onFailure(@NotNull Call<CategoryResult> call, @NotNull Throwable t) {
}
});
}
}
@Override
public void onFailure(@NotNull Call<CategoryResult> call, @NotNull Throwable t) {
}
});
}
}
@Override
public void onFailure(@NotNull Call<CategoryResult> call, @NotNull Throwable t) {
Log.d(TAG, "FAIL");
}
});
}
public void anim() {
if (isFabOpen) {
fab1.startAnimation(fab_close);
fab2.startAnimation(fab_close);
fab3.startAnimation(fab_close);
fab1.setClickable(false);
fab2.setClickable(false);
fab3.setClickable(false);
isFabOpen = false;
} else {
fab1.startAnimation(fab_open);
fab2.startAnimation(fab_open);
fab3.startAnimation(fab_open);
fab1.setClickable(true);
fab2.setClickable(true);
fab3.setClickable(true);
isFabOpen = true;
}
}
@Override
public void onMapViewInitialized(MapView mapView) {
}
@Override
public void onMapViewCenterPointMoved(MapView mapView, MapPoint mapPoint) {
}
@Override
public void onMapViewZoomLevelChanged(MapView mapView, int i) {
}
//맵 한번 클릭시 호출
@Override
public void onMapViewSingleTapped(MapView mapView, MapPoint mapPoint) {
//검색창켜져있을때 맵클릭하면 검색창 사라지게함
recyclerView.setVisibility(View.GONE);
}
@Override
public void onMapViewDoubleTapped(MapView mapView, MapPoint mapPoint) {
}
@Override
public void onMapViewLongPressed(MapView mapView, MapPoint mapPoint) {
}
@Override
public void onMapViewDragStarted(MapView mapView, MapPoint mapPoint) {
}
@Override
public void onMapViewDragEnded(MapView mapView, MapPoint mapPoint) {
}
@Override
public void onMapViewMoveFinished(MapView mapView, MapPoint mapPoint) {
}
@Override
public void onDaumMapOpenAPIKeyAuthenticationResult(MapView mapView, int i, String s) {
}
@Override
public void onPOIItemSelected(MapView mapView, MapPOIItem mapPOIItem) {
}
// 길찾기 카카오맵 호출( 카카오맵앱이 없을 경우 플레이스토어 링크로 이동)
public void showMap(Uri geoLocation) {
Intent intent;
try {
FancyToast.makeText(getApplicationContext(), "카카오맵으로 길찾기를 시도합니다.", FancyToast.LENGTH_SHORT, FancyToast.INFO, true).show();
intent = new Intent(Intent.ACTION_VIEW, geoLocation);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
} catch (Exception e) {
FancyToast.makeText(getApplicationContext(), "길찾기에는 카카오맵이 필요합니다. 다운받아주시길 바랍니다.", FancyToast.LENGTH_SHORT, FancyToast.INFO, true).show();
intent = new Intent(Intent.ACTION_VIEW).setData(Uri.parse("https://play.google.com/store/apps/details?id=net.daum.android.map&hl=ko"));
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
@Override
public void onCalloutBalloonOfPOIItemTouched(MapView mapView, MapPOIItem mapPOIItem) {
}
//말풍선(POLLITEM) 클릭시 호출
@Override
public void onCalloutBalloonOfPOIItemTouched(MapView mapView, MapPOIItem mapPOIItem, MapPOIItem.CalloutBalloonButtonType calloutBalloonButtonType) {
double lat = mapPOIItem.getMapPoint().getMapPointGeoCoord().latitude;
double lng = mapPOIItem.getMapPoint().getMapPointGeoCoord().longitude;
Toast.makeText(this, mapPOIItem.getItemName(), Toast.LENGTH_SHORT).show();
CFAlertDialog.Builder builder = new CFAlertDialog.Builder(this);
builder.setDialogStyle(CFAlertDialog.CFAlertStyle.ALERT);
builder.setTitle("선택해주세요");
builder.setSingleChoiceItems(new String[]{"장소 정보", "길찾기"}, 2, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int index) {
if (index == 0) {
mLoaderLayout.setVisibility(View.VISIBLE);
ApiInterface apiInterface = ApiClient.getApiClient().create(ApiInterface.class);
Call<CategoryResult> call = apiInterface.getSearchLocationDetail(getString(R.string.restapi_key), mapPOIItem.getItemName(), String.valueOf(lat), String.valueOf(lng), 1);
call.enqueue(new Callback<CategoryResult>() {
@Override
public void onResponse(@NotNull Call<CategoryResult> call, @NotNull Response<CategoryResult> response) {
mLoaderLayout.setVisibility(View.GONE);
if (response.isSuccessful()) {
Intent intent = new Intent(MapActivity.this, PlaceDetailActivity.class);
assert response.body() != null;
intent.putExtra(IntentKey.PLACE_SEARCH_DETAIL_EXTRA, response.body().getDocuments().get(0));
startActivity(intent);
}
}
@Override
public void onFailure(Call<CategoryResult> call, Throwable t) {
FancyToast.makeText(getApplicationContext(), "해당장소에 대한 상세정보는 없습니다.", FancyToast.LENGTH_SHORT, FancyToast.ERROR, true).show();
mLoaderLayout.setVisibility(View.GONE);
Intent intent = new Intent(MapActivity.this, PlaceDetailActivity.class);
startActivity(intent);
}
});
} else if (index == 1) {
showMap(Uri.parse("daummaps://route?sp=" + mCurrentLat + "," + mCurrentLng + "&ep=" + lat + "," + lng + "&by=FOOT"));
}
}
});
builder.addButton("취소", -1, -1, CFAlertDialog.CFAlertActionStyle.POSITIVE, CFAlertDialog.CFAlertActionAlignment.END, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
});
builder.show();
}
// 마커 드래그이동시 호출
@Override
public void onDraggablePOIItemMoved(MapView mapView, MapPOIItem mapPOIItem, MapPoint mapPoint) {
MapPoint.GeoCoordinate mapPointGeo = mapPoint.getMapPointGeoCoord();
mSearchName = "드래그한 장소";
mSearchLng = mapPointGeo.longitude;
mSearchLat = mapPointGeo.latitude;
mMapView.setMapCenterPoint(MapPoint.mapPointWithGeoCoord(mSearchLat, mSearchLng), true);
searchMarker.setItemName(mSearchName);
MapPoint mapPoint2 = MapPoint.mapPointWithGeoCoord(mSearchLat, mSearchLng);
searchMarker.setMapPoint(mapPoint2);
searchMarker.setMarkerType(MapPOIItem.MarkerType.BluePin); // 기본으로 제공하는 BluePin 마커 모양.
searchMarker.setSelectedMarkerType(MapPOIItem.MarkerType.RedPin); // 마커를 클릭했을때, 기본으로 제공하는 RedPin 마커 모양.
searchMarker.setDraggable(true);
mMapView.addPOIItem(searchMarker);
}
/*
* 현재 위치 업데이트(setCurrentLocationEventListener)
*/
@Override
public void onCurrentLocationUpdate(MapView mapView, MapPoint mapPoint, float accuracyInMeters) {
MapPoint.GeoCoordinate mapPointGeo = mapPoint.getMapPointGeoCoord();
Log.i(TAG, String.format("MapView onCurrentLocationUpdate (%f,%f) accuracy (%f)", mapPointGeo.latitude, mapPointGeo.longitude, accuracyInMeters));
currentMapPoint = MapPoint.mapPointWithGeoCoord(mapPointGeo.latitude, mapPointGeo.longitude);
//이 좌표로 지도 중심 이동
mMapView.setMapCenterPoint(currentMapPoint, true);
//전역변수로 현재 좌표 저장
mCurrentLat = mapPointGeo.latitude;
mCurrentLng = mapPointGeo.longitude;
Log.d(TAG, "현재위치 => " + mCurrentLat + " " + mCurrentLng);
mLoaderLayout.setVisibility(View.GONE);
//트래킹 모드가 아닌 단순 현재위치 업데이트일 경우, 한번만 위치 업데이트하고 트래킹을 중단시키기 위한 로직
if (!isTrackingMode) {
mMapView.setCurrentLocationTrackingMode(MapView.CurrentLocationTrackingMode.TrackingModeOff);
}
}
@Override
public void onCurrentLocationDeviceHeadingUpdate(MapView mapView, float v) {
}
@Override
public void onCurrentLocationUpdateFailed(MapView mapView) {
Log.i(TAG, "onCurrentLocationUpdateFailed");
mMapView.setCurrentLocationTrackingMode(MapView.CurrentLocationTrackingMode.TrackingModeOnWithoutHeading);
}
@Override
public void onCurrentLocationUpdateCancelled(MapView mapView) {
Log.i(TAG, "onCurrentLocationUpdateCancelled");
mMapView.setCurrentLocationTrackingMode(MapView.CurrentLocationTrackingMode.TrackingModeOnWithoutHeading);
}
@Subscribe //검색예시 클릭시 이벤트 오토버스
public void search(Document document) {//public항상 붙여줘야함
FancyToast.makeText(getApplicationContext(), document.getPlaceName() + " 검색", FancyToast.LENGTH_SHORT, FancyToast.SUCCESS, true).show();
mSearchName = document.getPlaceName();
mSearchLng = Double.parseDouble(document.getX());
mSearchLat = Double.parseDouble(document.getY());
mMapView.setMapCenterPoint(MapPoint.mapPointWithGeoCoord(mSearchLat, mSearchLng), true);
mMapView.removePOIItem(searchMarker);
searchMarker.setItemName(mSearchName);
searchMarker.setTag(10000);
MapPoint mapPoint = MapPoint.mapPointWithGeoCoord(mSearchLat, mSearchLng);
searchMarker.setMapPoint(mapPoint);
searchMarker.setMarkerType(MapPOIItem.MarkerType.BluePin); // 기본으로 제공하는 BluePin 마커 모양.
searchMarker.setSelectedMarkerType(MapPOIItem.MarkerType.RedPin); // 마커를 클릭했을때, 기본으로 제공하는 RedPin 마커 모양.
//마커 드래그 가능하게 설정
searchMarker.setDraggable(true);
mMapView.addPOIItem(searchMarker);
}
@Override
public void finish() {
super.finish();
bus.unregister(this); //이액티비티 떠나면 정류소 해제해줌
}
@Override
protected void onDestroy() {
super.onDestroy();
mMapView.setCurrentLocationTrackingMode(MapView.CurrentLocationTrackingMode.TrackingModeOff);
mMapView.setShowCurrentLocationMarker(false);
}
@Override
public void onBackPressed() {
super.onBackPressed();
}
}
[activity_map.xml]
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".activities.MapActivity"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<LinearLayout
android:layout_marginTop="4dp"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal"
>
<EditText
android:fontFamily="@font/binggraemelona"
android:hint="검색할 장소를 입력 후 선택해주세요"
android:id="@+id/map_et_search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/map_recyclerview"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="400dp"/>
<RelativeLayout
android:id="@+id/map_mv_mapcontainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
/>
</LinearLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginRight="15sp"
android:layout_marginBottom="230dp"
android:src="@drawable/ic_search_black_24dp"
android:visibility="invisible"
app:backgroundTint="#ffffff"
app:elevation="6dp"
app:pressedTranslationZ="12dp"
/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginRight="15sp"
android:layout_marginBottom="160dp"
android:src="@drawable/ic_current_location_seach_black_24dp"
android:visibility="invisible"
app:backgroundTint="#ffffff"
app:elevation="6dp"
app:pressedTranslationZ="12dp"
/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginRight="15sp"
android:layout_marginBottom="90dp"
android:src="@drawable/ic_location_searching_black_24dp"
android:visibility="invisible"
app:backgroundTint="#ffffff"
app:elevation="6dp"
app:pressedTranslationZ="12dp"
/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="15sp"
android:backgroundTint="@color/colorPrimary"
android:src="@drawable/ic_add_black_24dp"
/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_detail"
android:layout_width="wrap_content"
android:visibility="gone"
android:layout_height="wrap_content"
android:layout_gravity="bottom|start"
android:layout_margin="15sp"
android:src="@drawable/ic_search_detail_mint_24dp"
/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_stop_tracking"
android:layout_width="wrap_content"
android:visibility="gone"
android:layout_height="wrap_content"
android:layout_gravity="bottom|start"
android:layout_margin="15sp"
android:src="@drawable/ic_stop_red_24dp"
/>
<include
layout="@layout/view_loader"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
REST API 와 통신하기위한 retorfit2 코드
문서 :
developers.kakao.com/docs/latest/ko/local/dev-guide
Kakao Developers
카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.
developers.kakao.com
[ApiClient.java]
package com.mtjin.mapogreen.api;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class ApiClient {
private static final String BASE_URL = "https://dapi.kakao.com/";
private static Retrofit retrofit;
public static Retrofit getApiClient(){
if(retrofit == null){
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
[ApiInterface]
키워드로 장소검색 (장소이름으로 검색) 예시
package com.mtjin.mapogreen.api;
import com.mtjin.mapogreen.model.address_search.AddressSearch;
import com.mtjin.mapogreen.model.research.SearchResult;
import com.mtjin.mapogreen.model.category_search.CategoryResult;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Header;
import retrofit2.http.Query;
public interface ApiInterface {
//장소이름으로 검색
@GET("v2/local/search/keyword.json")
Call<CategoryResult> getSearchLocation(
@Header("Authorization") String token,
@Query("query") String query,
@Query("size") int size
);
//카테고리로 검색
@GET("v2/local/search/category.json")
Call<CategoryResult> getSearchCategory(
@Header("Authorization") String token,
@Query("category_group_code") String category_group_code,
@Query("x") String x,
@Query("y") String y,
@Query("radius") int radius
);
//장소이름으로 특정위치기준으로 검색
@GET("v2/local/search/keyword.json")
Call<CategoryResult> getSearchLocationDetail(
@Header("Authorization") String token,
@Query("query") String query,
@Query("x") String x,
@Query("y") String y,
@Query("size") int size
);
//주소로 검색 (아직안쓰는중)
@GET("v2/local/search/address.json")
Call<AddressSearch> getSearchAddress(
@Header("Authorization") String token,
@Query("query") String query,
@Query("size") int size
);
}
[model]
CategoryResult
package com.mtjin.mapogreen.model.category_search;
import android.os.Parcel;
import android.os.Parcelable;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
import java.util.ArrayList;
import java.util.List;
public class CategoryResult implements Parcelable {
@SerializedName("meta")
@Expose
private Meta meta;
@SerializedName("documents")
@Expose
private List<Document> documents = null;
public Meta getMeta() {
return meta;
}
public void setMeta(Meta meta) {
this.meta = meta;
}
public List<Document> getDocuments() {
return documents;
}
public void setDocuments(List<Document> documents) {
this.documents = documents;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(this.meta, flags);
dest.writeList(this.documents);
}
public CategoryResult() {
}
protected CategoryResult(Parcel in) {
this.meta = in.readParcelable(Meta.class.getClassLoader());
this.documents = new ArrayList<Document>();
in.readList(this.documents, Document.class.getClassLoader());
}
public static final Parcelable.Creator<CategoryResult> CREATOR = new Parcelable.Creator<CategoryResult>() {
@Override
public CategoryResult createFromParcel(Parcel source) {
return new CategoryResult(source);
}
@Override
public CategoryResult[] newArray(int size) {
return new CategoryResult[size];
}
};
}
Document
package com.mtjin.mapogreen.model.category_search;
import android.os.Parcel;
import android.os.Parcelable;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Document implements Parcelable {
@SerializedName("place_name")
@Expose
private String placeName;
@SerializedName("distance")
@Expose
private String distance;
@SerializedName("place_url")
@Expose
private String placeUrl;
@SerializedName("category_name")
@Expose
private String categoryName;
@SerializedName("address_name")
@Expose
private String addressName;
@SerializedName("road_address_name")
@Expose
private String roadAddressName;
@SerializedName("id")
@Expose
private String id;
@SerializedName("phone")
@Expose
private String phone;
@SerializedName("category_group_code")
@Expose
private String categoryGroupCode;
@SerializedName("category_group_name")
@Expose
private String categoryGroupName;
@SerializedName("x")
@Expose
private String x;
@SerializedName("y")
@Expose
private String y;
public String getPlaceName() {
return placeName;
}
public void setPlaceName(String placeName) {
this.placeName = placeName;
}
public String getDistance() {
return distance;
}
public void setDistance(String distance) {
this.distance = distance;
}
public String getPlaceUrl() {
return placeUrl;
}
public void setPlaceUrl(String placeUrl) {
this.placeUrl = placeUrl;
}
public String getCategoryName() {
return categoryName;
}
public void setCategoryName(String categoryName) {
this.categoryName = categoryName;
}
public String getAddressName() {
return addressName;
}
public void setAddressName(String addressName) {
this.addressName = addressName;
}
public String getRoadAddressName() {
return roadAddressName;
}
public void setRoadAddressName(String roadAddressName) {
this.roadAddressName = roadAddressName;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getPhone() {
return phone;
}
public void setPhone(String phone) {
this.phone = phone;
}
public String getCategoryGroupCode() {
return categoryGroupCode;
}
public void setCategoryGroupCode(String categoryGroupCode) {
this.categoryGroupCode = categoryGroupCode;
}
public String getCategoryGroupName() {
return categoryGroupName;
}
public void setCategoryGroupName(String categoryGroupName) {
this.categoryGroupName = categoryGroupName;
}
public String getX() {
return x;
}
public void setX(String x) {
this.x = x;
}
public String getY() {
return y;
}
public void setY(String y) {
this.y = y;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.placeName);
dest.writeString(this.distance);
dest.writeString(this.placeUrl);
dest.writeString(this.categoryName);
dest.writeString(this.addressName);
dest.writeString(this.roadAddressName);
dest.writeString(this.id);
dest.writeString(this.phone);
dest.writeString(this.categoryGroupCode);
dest.writeString(this.categoryGroupName);
dest.writeString(this.x);
dest.writeString(this.y);
}
public Document() {
}
protected Document(Parcel in) {
this.placeName = in.readString();
this.distance = in.readString();
this.placeUrl = in.readString();
this.categoryName = in.readString();
this.addressName = in.readString();
this.roadAddressName = in.readString();
this.id = in.readString();
this.phone = in.readString();
this.categoryGroupCode = in.readString();
this.categoryGroupName = in.readString();
this.x = in.readString();
this.y = in.readString();
}
public static final Parcelable.Creator<Document> CREATOR = new Parcelable.Creator<Document>() {
@Override
public Document createFromParcel(Parcel source) {
return new Document(source);
}
@Override
public Document[] newArray(int size) {
return new Document[size];
}
};
}
Meta
package com.mtjin.mapogreen.model.category_search;
import android.os.Parcel;
import android.os.Parcelable;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Meta implements Parcelable {
@SerializedName("same_name")
@Expose
private SameName sameName;
@SerializedName("pageable_count")
@Expose
private Integer pageableCount;
@SerializedName("total_count")
@Expose
private Integer totalCount;
@SerializedName("is_end")
@Expose
private Boolean isEnd;
public SameName getSameName() {
return sameName;
}
public void setSameName(SameName sameName) {
this.sameName = sameName;
}
public Integer getPageableCount() {
return pageableCount;
}
public void setPageableCount(Integer pageableCount) {
this.pageableCount = pageableCount;
}
public Integer getTotalCount() {
return totalCount;
}
public void setTotalCount(Integer totalCount) {
this.totalCount = totalCount;
}
public Boolean getIsEnd() {
return isEnd;
}
public void setIsEnd(Boolean isEnd) {
this.isEnd = isEnd;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeParcelable(this.sameName, flags);
dest.writeValue(this.pageableCount);
dest.writeValue(this.totalCount);
dest.writeValue(this.isEnd);
}
public Meta() {
}
protected Meta(Parcel in) {
this.sameName = in.readParcelable(SameName.class.getClassLoader());
this.pageableCount = (Integer) in.readValue(Integer.class.getClassLoader());
this.totalCount = (Integer) in.readValue(Integer.class.getClassLoader());
this.isEnd = (Boolean) in.readValue(Boolean.class.getClassLoader());
}
public static final Creator<Meta> CREATOR = new Creator<Meta>() {
@Override
public Meta createFromParcel(Parcel source) {
return new Meta(source);
}
@Override
public Meta[] newArray(int size) {
return new Meta[size];
}
};
}
SameName
package com.mtjin.mapogreen.model.category_search;
import android.os.Parcel;
import android.os.Parcelable;
import java.util.ArrayList;
import java.util.List;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class SameName implements Parcelable {
@SerializedName("region")
@Expose
private List<Object> region = null;
@SerializedName("keyword")
@Expose
private String keyword;
@SerializedName("selected_region")
@Expose
private String selectedRegion;
public List<Object> getRegion() {
return region;
}
public void setRegion(List<Object> region) {
this.region = region;
}
public String getKeyword() {
return keyword;
}
public void setKeyword(String keyword) {
this.keyword = keyword;
}
public String getSelectedRegion() {
return selectedRegion;
}
public void setSelectedRegion(String selectedRegion) {
this.selectedRegion = selectedRegion;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeList(this.region);
dest.writeString(this.keyword);
dest.writeString(this.selectedRegion);
}
public SameName() {
}
protected SameName(Parcel in) {
this.region = new ArrayList<Object>();
in.readList(this.region, Object.class.getClassLoader());
this.keyword = in.readString();
this.selectedRegion = in.readString();
}
public static final Creator<SameName> CREATOR = new Creator<SameName>() {
@Override
public SameName createFromParcel(Parcel source) {
return new SameName(source);
}
@Override
public SameName[] newArray(int size) {
return new SameName[size];
}
};
}
[인앱 사진]
[포스팅 댓글에서 요청한 xml]
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".activities.MapActivity"
>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<LinearLayout
android:layout_marginTop="4dp"
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal"
>
<EditText
android:fontFamily="@font/binggraemelona"
android:hint="검색할 장소를 입력 후 선택해주세요"
android:id="@+id/map_et_search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/map_recyclerview"
android:visibility="gone"
android:layout_width="match_parent"
android:layout_height="400dp"/>
<RelativeLayout
android:id="@+id/map_mv_mapcontainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
/>
</LinearLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginRight="15sp"
android:layout_marginBottom="230dp"
android:src="@drawable/ic_search_black_24dp"
android:visibility="invisible"
app:backgroundTint="#ffffff"
app:elevation="6dp"
app:pressedTranslationZ="12dp"
/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginRight="15sp"
android:layout_marginBottom="160dp"
android:src="@drawable/ic_current_location_seach_black_24dp"
android:visibility="invisible"
app:backgroundTint="#ffffff"
app:elevation="6dp"
app:pressedTranslationZ="12dp"
/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginRight="15sp"
android:layout_marginBottom="90dp"
android:src="@drawable/ic_location_searching_black_24dp"
android:visibility="invisible"
app:backgroundTint="#ffffff"
app:elevation="6dp"
app:pressedTranslationZ="12dp"
/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="15sp"
android:backgroundTint="@color/colorPrimary"
android:src="@drawable/ic_add_black_24dp"
/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_detail"
android:layout_width="wrap_content"
android:visibility="gone"
android:layout_height="wrap_content"
android:layout_gravity="bottom|start"
android:layout_margin="15sp"
android:src="@drawable/ic_search_detail_mint_24dp"
/>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab_stop_tracking"
android:layout_width="wrap_content"
android:visibility="gone"
android:layout_height="wrap_content"
android:layout_gravity="bottom|start"
android:layout_margin="15sp"
android:src="@drawable/ic_stop_red_24dp"
/>
<include
layout="@layout/view_loader"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
'안드로이드 > 자바 & Previous' 카테고리의 다른 글
[안드로이드] 원형차트(Radar Chart) (0) | 2020.01.05 |
---|---|
[안드로이드] 카카오맵(kakao map) 에러 (4) | 2019.12.29 |
[안드로이드] 서버 소켓 프로그래밍 (채팅) (0) | 2019.12.18 |
[안드로이드] Retrofit2 @Body @Field 차이 (5) | 2019.11.07 |
[안드로이드] 부스트코스 7단원 멀티미디어 내용요약 (0) | 2019.09.03 |