В первой части мы проанализировали наши требования и имеющиеся в нашем распоряжении инструменты, чтобы получить первоначальный дизайн приложения.
Эта часть начнет реализацию с класса более низкого уровня, LocatorOverlay , и ответит на следующий вопрос: Какие функции мы хотим предоставить поверх карты местоположений телефона? Простое отображение местоположения на экране телефона — это мило … около десяти секунд. Поэтому нам нужно подумать о добавленной функциональности.
Здесь мы реализуем функцию «отправить местоположение контакту»: пользователь может просто нажать на точку местоположения своего телефона на карте и поделиться ею с любым количеством контактов посредством SMS.
Для наложения элементов Google Карты предоставляют нам несколько вариантов выбора в качестве базовых классов, которые могут быть расширены для наследования функциональности:
- Overlay абстрактный класс
- ItemizedOverlay подкласс Overlay, который мы можем использовать в качестве списка наложения элементов.
- MyLocationOverlay подкласс Overlay, который рисует местоположение пользователя на карте.
Второй вариант — хороший выбор, если мы намереваемся отобразить несколько элементов поверх карты. Давайте начнем писать первый черновик нашего класса LocatorOverlay :
//...package statement and other imports go here //... import com.google.android.maps.ItemizedOverlay; import com.google.android.maps.OverlayItem; /** * Custom overlay class */ public class LocatorOverlay extends ItemizedOverlay<OverlayItem> { private List<OverlayItem> mapOverlays = new ArrayList<OverlayItem>(); private Context context; public LocatorOverlay(Drawable defaultMarker) { super(boundCenterBottom(defaultMarker)); } public LocatorOverlay(Drawable defaultMarker, Context context) { this(defaultMarker); this.context = context; }
public void addOverlay(OverlayItem overlay) { mapOverlays.add(overlay); this.populate(); } @Override protected OverlayItem createItem(int i) { return mapOverlays.get(i); } @Override public int size() { return mapOverlays.size(); } @Override protected boolean onTap(int index) { // TODO return true; } }
Пока ничего необычного. У нас есть список элементов наложения и ссылка на контекст приложения. Последний метод onTap (int index) — то, где вещи становятся интересными. Давайте реализуем диалоговое окно отправки-размещения-через-SMS, которое всплывает, когда пользователь нажимает на точку расположения телефона:
/** * Show some info and send location via SMS * * @param index * @return */ @Override protected boolean onTap(int index) { // Items to display in the dialog OverlayItem item = mapOverlays.get(index); //? see Part 3 AlertDialog.Builder dialog = new AlertDialog.Builder(context); dialog.setTitle(item.getTitle()); dialog.setMessage(item.getSnippet()); // get location in the format "latitude,longitude" final String address = item.routableAddress(); // dialog to send location via SMS dialog.setCancelable(false); dialog.setPositiveButton("Send Location", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // call SMS program Intent sendIntent = new Intent(Intent.ACTION_VIEW); sendIntent.putExtra("sms_body", "My location: " + address); sendIntent.setType("vnd.android-dir/mms-sms"); context.startActivity(sendIntent); } }) ; dialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.dismiss(); } }); dialog.show(); return true; }
То, что мы сделали, было:
- Получить список элементов для наложения (здесь отображаются как часть заголовка и сообщения диалога)
- Создайте диалог, чтобы включить отправку местоположения с помощью SMS
- Включить местоположение в тексте сообщения SMS
Но откуда список элементов наложения mapOverlays получает элементы OverlayItem ? Мы увидим это в части 3. А пока, вот как он будет выглядеть в конце, когда пользователь нажмет на точку расположения на первом снимке экрана:
Мы закончили с отображением местоположения по SMS? Не совсем. Видите, «адрес», который мы получаем из OverlayItem .routableAddress (), содержит только пару широта и долгота и имеет ограниченное практическое использование. Однако ничто не мешает нам создать URL-адрес карты Google с этими координатами, чтобы наши получатели SMS могли щелкнуть ссылку и визуализировать наше местоположение в своем браузере. Например, мы могли бы сделать это:
String latLong = item.routableAddress(); final String locationURL = "https://maps.google.com/maps?q=" + URLEncoder.encode(latLong); // code .... // send locationURL instead of initial address sendIntent.putExtra("sms_body", locationURL); // code ...
Мы могли бы стать еще более изощренными и использовать API URL Shortener Google для нашего URL местоположения. Если, с другой стороны, мы предпочитаем отправлять адрес улицы, соответствующий (более или менее) паре широта-долгота, нам нужно использовать обратное геокодирование :
// new imports: import android.location.Address; import android.location.Geocoder; //... // inside onTap() method //get street address estimate GeoPoint point = item.getPoint(); String streetAddr = ""; Geocoder geoCoder = new Geocoder(context, Locale.getDefault()); try { // point's coordinates are stored in micro-degrees... List<Address> addrList = geoCoder.getFromLocation( point.getLatitudeE6() / 1E6, point.getLongitudeE6() / 1E6, 1); // max result = 1 if ( addrList != null && addrList .size() > 0) { // first addr in the list is closest estimate Address addr1 = addrList.get(0); streetAddr = addr1.getAddressLine(0) + ", " + addr1.getLocality(); } } catch (IOException e) { e.printStackTrace(); streetAddr = "Not Available (Network connection)"; } final String address = streetAddr; //code ... sendIntent.putExtra("sms_body", "My location: \n" + address); //code ...
Конечно, ничто не мешает нам отправлять получателю SMS и адрес местоположения, и адрес улицы . Однако имейте в виду, что в общем случае поиск в обратном геокодировании заметно замедляет время отклика приложения , и в этом случае время, необходимое для всплывающего диалогового окна в ответ на событие касания.
Мы закончили с LocatorOverlay . В третьей части мы реализуем класс Locator .
Из блога Тони .