1

2011 年 7 月 12 日更新:我想通了。完成实施后将立即发布解决方案。

我正在创建一个 Android 应用程序,它将在 Google 地图上显示多个用户的位置。用户当前在地图上表示为蓝点和绿点。当您点击代表您所在位置的蓝点时,地图上会出现一个自定义叠加层,上面写着“当前位置”

http://imgur.com/7S1Bg

我的问题是,当我滚动或缩放地图时,带有“当前位置”的叠加层保持在同一位置,而地图在其下方移动。我希望它与地图一起移动,以便弹出窗口始终位于蓝点的正上方,就像在这个例子中一样:

http://econym.org.uk/gmap/example_ewindow.htm

这是我的地图项目的布局方式:

我有一个扩展 com.google.android.maps.MapActivity 的 Activity。该活动有一个 com.google.android.maps.MapView 对象作为成员。我使用 AdjacentMapOverlayList(它扩展了 ItemizedOverlay)来管理叠加层。

这是用户单击蓝色图标时的代码:

/*
 * Handle tap events.
 * 
 * @param index the item that was tapped
 */
@Override
protected boolean onTap(int index) {

    Log.d(TAG, "User clicked something");

    // get the item that was tapped
    OverlayItem item = (OverlayItem) getItem(index);

    // cast it
    AdjacentUserOverlay overlay = (AdjacentUserOverlay) item;

    // get the point from the item
    GeoPoint geo = overlay.getPoint();
    Point pt = m_mapView.getProjection().toPixels(geo, null);

    // display the dialog
    m_userPopupDialog.show(pt.x, pt.y);

    // true dat
    return true;
}

我猜我需要拦截地图移动事件并手动移动弹出对话框,但必须有一个更简单的方法。谁能解释如何做到这一点?如果您需要任何其他信息,我会全天待命。感谢您的任何建议!

4

1 回答 1

1

我想到了。这是我扩展 com.google.android.maps.Overlay 的类:

package com.joshuawitter.maps;

import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.RectF;
import android.util.Log;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;
import com.google.android.maps.Overlay;
import com.google.android.maps.Projection;
import com.joshuawitter.Base64;

/*
 * UsersOverlay.java
 * 
 * Description: The Google Maps overlay that displays the users on the map screen.
 * 
 * Author: Joshua Witter
 */

public class UsersOverlay extends Overlay {

    private static final String TAG = "Josh-UsersOverlay";

    // the activity that called this overlay
    private Activity m_caller;

    // the currently selected User
    private UserOnMap m_selectedUser;

    // list of User locations
    private ArrayList<UserOnMap> m_Users;

    // set the list of Users
    public void setUsers(ArrayList<UserOnMap> users) {

        // set the list of Users
        this.m_Users = users;
    }

    /*
     * Parameterized constructor.
     * 
     * @param caller the activity that created this overlay
     * @param Users a list of the Users to display
     */
    public UsersOverlay(Activity caller) {
        super();

        // reference the caller
        m_caller = caller;

        // make a new list of Users
        m_Users = new ArrayList<UserOnMap>(0);
    }

    /*
     * User tapped the map.
     * 
     * @param geoPoint the location the user tapped
     * @param mapView the map itself
     */
    @Override
    public boolean onTap(GeoPoint geoPoint, MapView mapView) {

        // get the User that was tapped
        UserOnMap user = getTappedUser(mapView, geoPoint);

        // if the user tapped on a User
        if (null != user) {

            // if this User is not already selected, select it
            m_selectedUser = (m_selectedUser != user) ? user : null;
        }

        // otherwise the user tapped nothing
        else {

            // deselect the selected user
            m_selectedUser = null;
        }

        // call through to the parent
        return super.onTap(geoPoint, mapView);
    }

    /*
     * Draw the overlay on the map.
     * 
     * @param canvas the canvas to draw on
     * @param mapView the map view
     * @param shadow should we draw the shadow?
     */
    @Override
    public void draw(Canvas canvas, MapView mapView, boolean shadow) {

        // draw the User icons
        drawUserIcons(canvas, mapView);

        // call the parent draw method
        super.draw(canvas, mapView, shadow);
    }

    /*
     * Draw the User icons on the map.
     * 
     * @param canvas the canvas to draw on
     * @param mapView the map view
     */
    private void drawUserIcons(Canvas canvas, MapView mapView) {

        // loop through the users
        for (UserOnMap user : m_Users) {

            // draw the icon for the User
            drawUserIcon(canvas, mapView, user);
        }

        // draw the selected User last so that it is on top
        if (null != m_selectedUser) {
            drawUserBubble(canvas, mapView, m_selectedUser);
        }
    }

    /*
     * Draw a User bubble overlay.
     * 
     * @param canvas the canvas to draw on
     * @param mapView the map view
     * @param user the User we are displaying the information for
     */
    private void drawUserBubble(Canvas canvas, MapView mapView, UserOnMap user) {

        // get the overlay point
        Projection projection = mapView.getProjection();
        Point pt = new Point();
        projection.toPixels(user.getLocation(), pt);

        // get the bubble bitmap ready
        Bitmap bubbleBitmap = BitmapFactory
                .decodeResource(m_caller.getResources(),
                        R.drawable.user_bubble);

        // get the dimensions of the bubble
        int height = bubbleBitmap.getHeight();
        int width = bubbleBitmap.getWidth();

        // calculate the offsets
        int xValue = pt.x - (width / 2);
        int yValue = pt.y - height - 20;

        // draw the icon
        canvas.drawBitmap(bubbleBitmap, xValue, yValue, null);

        // get the paint object
        Paint paint = new Paint();
        paint.setStyle(Paint.Style.FILL);
        paint.setAntiAlias(true);
        paint.setTextSize(24);

        // draw the text
        canvas.drawText("Current Location", xValue + 30, yValue + 33, paint);
    }

    /*
     * Draw a User icon overlay.
     * 
     * @param canvas the canvas to draw on
     * @param mapView the map view
     * @param user the User we are displaying the icon for
     */
    private void drawUserIcon(Canvas canvas, MapView mapView,
            UserOnMap user) {

        // get the overlay point
        Projection projection = mapView.getProjection();
        Point pt = new Point();
        projection.toPixels(user.getLocation(), pt);

        // get the icon
        Bitmap icon = BitmapFactory.decodeResource(m_caller.getResources(),
                user.getIconResource());

        // get the dimensions of the icon
        int height = icon.getHeight();
        int width = icon.getWidth();

        // calculate the offsets
        int xValue = pt.x - (width / 2);
        int yValue = pt.y - height;

        // draw the icon
        canvas.drawBitmap(icon, xValue, yValue, null);
    }

    /*
     * Determine which User was tapped by the user.
     * 
     * @param tapPoint where the user tapped
     * @param mapView the map view
     * @param UserOnMap the User was tapped, null if none
     */
    private UserOnMap getTappedUser(MapView mapView, GeoPoint tapPoint) {

        // get the screen coordinates that match our tap
        Point tapScreenCoordinates = new Point();
        mapView.getProjection().toPixels(tapPoint, tapScreenCoordinates);

        // loop through the User icons
        for (UserOnMap user : m_Users) {

            // if this is the currently selected User
            if (user == m_selectedUser) {

                // if we tapped its bubble
                if (hitUserBubble(mapView, tapPoint, user)) {

                    // we found the User
                    Log.d(TAG, "User " + user.getLastName() + " was tapped (bubble)");
                    return user;

                }
            }

            // otherwise if we tapped the icon for an User 
            if (hitUserIcon(mapView, tapPoint, user)) {

                // return the User
                Log.d(TAG, "User " + user.getLastName() + " was tapped (icon)");
                return user;
            }
        }

        // return the tapped User
        return null;
    }

    /*
     * Determine if an User's icon was tapped by the user.
     * 
     * @param tapPoint where the user tapped
     * @param mapView the map view
     * @param User the User we are checking
     * @param boolean true if the icon for this User was tapped
     */
    private boolean hitUserIcon(MapView mapView, GeoPoint tapPoint,
            UserOnMap user) {

        // get the screen coordinates that match our tap
        Point tapScreenCoordinates = new Point();
        mapView.getProjection().toPixels(tapPoint, tapScreenCoordinates);

        // get the screen coordinates for the User's location
        Point iconScreenCoordinates = new Point();
        mapView.getProjection().toPixels(user.getLocation(),
                iconScreenCoordinates);

        // get the icon for the User
        Bitmap icon = BitmapFactory.decodeResource(m_caller.getResources(),
                user.getIconResource());

        // calculate the icon hit box size
        int xValue = 50;
        int yValue = 50;

        // create a rectangle representing our icon
        RectF iconRectangle = new RectF();
        iconRectangle.set(-xValue, -yValue, xValue, yValue);
        iconRectangle.offset(iconScreenCoordinates.x, iconScreenCoordinates.y);

        // return true if the user tapped on the icon for this User
        return (iconRectangle.contains(tapScreenCoordinates.x,
                tapScreenCoordinates.y));
    }

    /*
     * Determine if an User's bubble was tapped by the user.
     * 
     * @param tapPoint where the user tapped
     * @param mapView the map view
     * @param User the User we are checking
     * @param boolean true if the bubble for this User was tapped
     */
    private boolean hitUserBubble(MapView mapView, GeoPoint tapPoint,
            UserOnMap user) {

        // get the screen coordinates that match our tap
        Point tapScreenCoordinates = new Point();
        mapView.getProjection().toPixels(tapPoint, tapScreenCoordinates);

        // get the screen coordinates for the User's location
        Point iconScreenCoordinates = new Point();
        mapView.getProjection().toPixels(user.getLocation(),
                iconScreenCoordinates);

        // get the bubble for the User
        Bitmap bubble = BitmapFactory.decodeResource(m_caller.getResources(),
                R.drawable.backup_map_current_location);

        // calculate the bubble hit box size
        int xValue = bubble.getWidth() * 2;
        int yValue = bubble.getHeight() * 2;

        // create a rectangle representing our bubble
        RectF iconRectangle = new RectF();
        iconRectangle.set(-xValue, -yValue, xValue, yValue);
        iconRectangle.offset(iconScreenCoordinates.x, iconScreenCoordinates.y);

        // return true if the user tapped on the bubble
        return (iconRectangle.contains(tapScreenCoordinates.x,
                tapScreenCoordinates.y));
    }
}

我有一个由我的活动调用的服务(扩展 MapActivity),它返回一个用户列表。我只是拿那个列表并使用这个方法:

    // for each User we got back
    for (User user: response.getUsers()) {

        // get the location of the User
        GeoPoint userLocation = new GeoPoint(
                (int) (user.getLatitude() * 1E6),
                (int) (user.getLongitude() * 1E6));

        // create a map representation of the User
        UserOnMap userOnMap = new UserOnMap(user.getUserId(),
                user.getFirstName(), user.getLastName());

        // add the user to the list
        usersOnMap.add(userOnMap);
    }

    // set the overlay to reference this new list
    m_usersOverlay.setUsers(usersOnMap);

    // get the current list of map overlays
    List<Overlay> m_mapOverlays = m_mapView.getOverlays();
    m_mapOverlays.clear();
    m_mapOverlays.add(m_usersOverlay);
    m_mapView.invalidate();

如果您有任何问题,请告诉我。请忽略循环中的分配、奇怪的变量名等,这不仅是一个粗略的草稿,而且是一个模糊的草稿:-)

于 2011-12-08T21:35:28.187 回答