Наложение не рисуется в нужном месте
У меня очень странная проблема.
Прежде всего, когда я увеличиваю и уменьшаю масштаб MapView, маркер (наложение) перемещается в неправильные места (плохо работает с масштабированием).
Во-вторых, рынок тянет не в ту позицию!
Я выложу код ниже, но сначала послушайте это:
Я в Исламабаде. Геокодер также говорит мне, что я в Исламабаде. Но когда я рисую круг вокруг своего местоположения, используя оверлеи, он рисует его в городе, который находится на расстоянии сотен километров.
Пожалуйста, помогите мне с обеими проблемами.
Вот активность:
public class LocatePickup extends MapActivity implements LocationListener {
Geocoder gc;
MapView mapView;
MapController mc;
GeoPoint p;
double lat = 0;
double lng = 0;
LocationManager lm;
WebMethods wm;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.locate_pickup);
mapView = (MapView) findViewById(R.id.mapView);
mapView.setBuiltInZoomControls(true);
mapView.setStreetView(true);
lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
lm.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000L, 500.0f, this);
Location l = new Location(LocationManager.NETWORK_PROVIDER);
l = lm.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
mc = mapView.getController();
p = new GeoPoint((int) (l.getLatitude()), (int) (l.getLongitude()));
mc.setCenter(p);
mc.setZoom(14);
MapOverlay myLocationOverlay = new MapOverlay();
List<Overlay> list = mapView.getOverlays();
list.add(myLocationOverlay);
gc = new Geocoder(this);
try {
List<Address> address = gc.getFromLocation(l.getLatitude(), l.getLongitude(), 1);
Toast.makeText(this, ""+address.get(0).getAddressLine(1), 1).show();
}
catch (IOException e) {
e.printStackTrace();
}
}
@Override
protected boolean isRouteDisplayed() {
return false;
}
class MapOverlay extends com.google.android.maps.Overlay {
Paint paint = new Paint();
@Override
public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when) {
super.draw(canvas, mapView, shadow);
Point myScreenCoords = new Point();
mapView.getProjection().toPixels(p, myScreenCoords);
paint.setStrokeWidth(1);
paint.setARGB(255, 218, 28, 28);
paint.setStyle(Paint.Style.STROKE);
//Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.pin);
canvas.drawCircle(myScreenCoords.x, myScreenCoords.y, 15, paint);
//(bmp, myScreenCoords.x, myScreenCoords.y - 256, paint);
canvas.drawText("Hey!", myScreenCoords.x, myScreenCoords.y, paint);
return true;
}
}
@Override
public void onLocationChanged(Location arg0) {
if(arg0 != null) {
Log.d("New Location: ", arg0.getLatitude() + " - " + arg0.getLongitude());
lat = arg0.getLatitude();
lng = arg0.getLongitude();
p = new GeoPoint((int) lat * 1000000, (int) lng * 1000000);
mc.animateTo(p);
}
}
@Override
public void onProviderDisabled(String provider) {
// empty
}
@Override
public void onProviderEnabled(String provider) {
// empty
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
//empty
}
}
Когда код будет завершен, я бы хотел, чтобы пользователь мог нажать на точку на карте и получить ее адрес (маркер также должен переместиться в эту точку). Но это должно быть точно.
2 ответа
Так как никто не ответил на этот вопрос правильно..
По какой-то причине обычный класс Overlay не работал для меня так, как следовало бы. Я переключился на ItemizedOverlay и теперь все идеально.
Я не эксперт по Android, поэтому я хотел бы, чтобы кто-то с большим опытом прокомментировал это, но я чувствую, что ItemizedOverlay намного лучше, чем простое наложение. С помощью наложенного изображения, увеличение и уменьшение масштаба карты с объектом, нарисованным в фиксированной точке, работает так, как должно, булавка (объект) остается именно там, где и должна оставаться (чего не было раньше).
Вот код для тех, кто его ищет. Это, конечно, неполно, и для конкретной цели, но вы получите общее представление.
`class CustomOverlay extends com.google.android.maps.ItemizedOverlay {private ArrayList mOverlays = new ArrayList (); Контекст mContext;
public CustomOverlay(Drawable defaultMarker)
{
super(defaultMarker);
}
public void addOverlay(OverlayItem overlay)
{
mOverlays.add(overlay);
populate();
}
@Override
protected OverlayItem createItem(int i)
{
return mOverlays.get(i);
}
@Override
public int size()
{
return mOverlays.size();
}
public CustomOverlay(Drawable defaultMarker, Context context)
{
super(boundCenterBottom(defaultMarker));
mContext = context;
}
@Override
public boolean onTouchEvent(MotionEvent event, MapView mapView)
{
if (event.getAction() == 1)
{
p = mapView.getProjection().fromPixels((int) event.getX(),
(int) event.getY());
gc = new Geocoder(getBaseContext(), Locale.getDefault());
try
{
address = gc.getFromLocation(
(double) p.getLatitudeE6() / 1E6,
(double) p.getLongitudeE6() / 1E6, 1);
addressfound = true;
}
catch (IOException e)
{
addressfound = false;
e.printStackTrace();
}
if (address.size() != 0)
{
l1 = address.get(0).getAddressLine(0);
l2 = address.get(0).getAddressLine(1);
l3 = address.get(0).getAddressLine(2);
}
OverlayItem point = new OverlayItem(p, "Location", l1 + ", "
+ l2 + ", " + l3);
List<Overlay> mapOverlays = mapView.getOverlays();
Drawable drawable = getBaseContext().getResources()
.getDrawable(R.drawable.androidmarker);
CustomOverlay itemizedoverlay = new CustomOverlay(drawable,
getBaseContext());
itemizedoverlay.addOverlay(point);
mapOverlays.clear();
mapOverlays.add(itemizedoverlay);
mapView.invalidate();
}`
Чтобы анимировать карту к данному геопункту, используйте метод animateTo(),
Так что реализуйте zoomListener в вашем методе, и добавьте строку,
mapController.animateTo(geoPoint);
Кроме того, попробуйте mapview.invalidate()
И, между прочим, если вы не знаете, как реализовать слушатель масштабирования, обратитесь к разделу Как реализовать OnZoomListener в MapView.
для второго вопроса, вы использовали только NETWORK_PROVIDER
что менее точно, чем использование GPS для получения значений местоположения. Так что попробуйте использовать GPS_PROVIDER
Эффективное и правильное внедрение может дать вам более точные значения.
И чтобы получить широту и долготу точки, затронутой на карте, в mapOverlay
класс реализовать onTouchEvent
@Override
public boolean onTouchEvent(MotionEvent event, MapView mapView)
{
//---when user lifts his finger---
if (event.getAction() == 1) {
GeoPoint p = mapView.getProjection().fromPixels(
(int) event.getX(),
(int) event.getY());
Toast.makeText(getBaseContext(),
p.getLatitudeE6() / 1E6 + "," +
p.getLongitudeE6() /1E6 ,
Toast.LENGTH_SHORT).show();
}
return false;
}
Вы можете получить адрес от широты и долготы, используя GeoCoder
Geocoder geoCoder = new Geocoder(
getBaseContext(), Locale.getDefault());
try {
List<Address> addresses = geoCoder.getFromLocation(latitude/1E6,
longitude / 1E6, 1);
String add = "";
if (addresses.size() > 0)
{
for (int i=0; i<addresses.get(0).getMaxAddressLineIndex();
i++)
add += addresses.get(0).getAddressLine(i) + "\n";
}
Toast.makeText(getBaseContext(), add, Toast.LENGTH_SHORT).show();
}catch (IOException e) {
e.printStackTrace();
}
Если вы хотите добавить маркер к этой точке, добавьте overlayItem
для этого пункта и добавьте его в оверлей.