В первой части мы проанализировали наши требования и имеющиеся в нашем распоряжении инструменты, чтобы получить первоначальный дизайн приложения.
![]() |
Эта часть начнет реализацию с класса более низкого уровня, 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 .
Из блога Тони .


