2010-01-06 43 views
37

Chúng tôi đang xây dựng một ứng dụng đang sử dụng api bản đồ google cho android.Trên sự kiện thu phóng cho bản đồ google trên android

Tôi có MapController và MapView của tôi, và tôi cho phép được xây dựng trong điều khiển zoom sử dụng:

mapView.setBuiltInZoomControls(true); 

bây giờ tôi muốn có được một sự kiện khi người dùng thực sự phóng trên bản đồ, làm thế nào để tôi đi về điều đó? Tôi không thể tìm thấy sự kiện như vậy hoặc bất kỳ sự kiện chung nào mà tôi có thể phát hiện sự thay đổi về mức thu phóng.

Cập nhật

The mapView.getZoomControls() is deprecated. Và tài liệu cho thấy sử dụng mapView.setBuiltInZoomControls (bool) thay thế. Điều này là ổn, nhưng tôi chỉ đơn giản là không thể tìm ra cách để hành động trên các sự kiện từ các điều khiển zoom tích hợp.

+3

Tôi đã thử triển khai sự kiện onUserInteraction, cho cùng một mục đích nhưng tôi vẫn gặp sự cố. Tôi đang hiển thị một hình ảnh cần được thu nhỏ theo mức thu phóng, vì vậy rõ ràng là tôi muốn gọi phương thức redraw() khi người dùng phóng to. Vấn đề của tôi là onUserInteraction được gọi khi người dùng nhấp vào nút thu phóng, vì vậy zoomLevel chưa được cập nhật và chỉ trên tương tác tiếp theo (nhấp, span, bất kỳ) zoomLevel được cập nhật. Vì vậy, hình ảnh của tôi chỉ được cập nhật sau khi tương tác sau khi thu phóng thực tế. Bất kỳ ý tưởng? – Itsik

+1

Câu hỏi và câu trả lời này đề cập đến API v1, tôi đã thêm câu trả lời mới bên dưới cho người đang sử dụng [Google Maps Android API v2] (https://developers.google.com/maps/documentation/android /) – tarmelop

Trả lời

37

Với API v2 Google Maps dành cho Android bạn có thể sử dụng một GoogleMap.OnCameraChangeListener như thế này:

mMap.setOnCameraChangeListener(new OnCameraChangeListener() { 

    private float currentZoom = -1; 

    @Override 
    public void onCameraChange(CameraPosition pos) { 
     if (pos.zoom != currentZoom){ 
      currentZoom = pos.zoom; 
      // do you action here 
     } 
    } 
}); 
+3

'setOnCameraChangeListener()' hiện không còn được dùng nữa –

4

Các android API gợi ý bạn sử dụng ZoomControls trong đó có một setOnZoomInClickListener()

Để thêm các điều khiển zoom bạn sẽ:

ZoomControls mZoom = (ZoomControls) mapView.getZoomControls(); 

Và sau đó thêm mZoom để bố trí của bạn.

+0

Cảm ơn câu trả lời. MapView.getZoomControls() không được chấp nhận, với đề xuất sử dụng phương thức MapView.setBuiltInZoomControls (boolean). Nhưng tôi không thể tìm thấy bất cứ nơi nào để có được bất kỳ sự kiện từ các điều khiển zoom tích hợp. Tham khảo: http://code.google.com/android/add-ons/google-apis/reference/com/google/android/maps/MapView.html#getZoomControls(). –

+0

Tôi hiểu. Vâng, có vẻ như có một mapView.getZoomButtonsController() mà bạn có thể sử dụng, được mô tả trong http://code.google.com/p/android/issues/detail?id=3348 nếu không bạn sẽ chỉ phải sử dụng mapview.onkeydown và kiểm tra để thu phóng. – JasonOfEarth

+0

Tôi nhận được những gì tôi muốn bằng cách sử dụng sự kiện onUserInteraction và thử nghiệm thủ công cho một thay đổi ở mức thu phóng. Nó hoạt động thực sự tốt đẹp với một tin nhắn chúc mừng thông báo cho người dùng về sự cần thiết phải phóng to để xem lớp phủ của tôi. –

5

Khi OP cho biết, hãy sử dụng onUserInteractionEvent và tự mình làm bài kiểm tra.

+3

'onUserInteractionEvent()' được gọi là * trước * thay đổi mức thu phóng. Điều này có nghĩa là với mỗi sự kiện zoom, ứng dụng giám sát zoom đang chạy một sự kiện phía sau. –

+0

@Paul: Xin chào. Ban đầu tôi đã không xem xét điều này, nhưng có vẻ như bạn là đúng, bánh mì nướng tôi hiển thị luôn luôn là một ngay cả phía sau. –

+1

Bạn có thể tạo một cá thể 'Handler' và kiểm tra định kỳ các thay đổi mức thu phóng thông qua một cái gì đó như' postDelayed (new Runnable() {...}, 500) ', nhưng tôi thực sự không thích giải pháp đó. –

4

Bạn có thể sử dụng

ZoomButtonsController zoomButton = mapView.getZoomButtonsController(); 
zoomButton.setOnZoomListener(listener); 

hy vọng nó sẽ giúp

+2

Điều này đặc biệt trả lời câu hỏi của OP, nhưng chỉ đặt ra một sự kiện cho các sự kiện thu phóng thông qua các nút thu phóng. Ví dụ, việc véo không kêu gọi gọi lại của người nghe. –

2

U có thể có zoom CControl như thế này.

Ở đây tôi đang gắn mã làm cách nào bạn có thể triển khai zoomcontrol.

1 >> Tệp XML phải như thế này.

<?xml version="1.0" encoding="utf-8"?> 
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"> 

    <com.google.android.maps.MapView 
     android:id="@+id/mapView" 
     android:layout_width="fill_parent" 
     android:layout_height="fill_parent" 
     android:enabled="true" 
     android:clickable="true" 
     android:apiKey="0l4sCTTyRmXTNo7k8DREHvEaLar2UmHGwnhZVHQ" 
     /> 

    <LinearLayout android:id="@+id/zoom" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:layout_alignParentBottom="true" 
     android:layout_centerHorizontal="true" 
     /> 

</RelativeLayout> 

2 >> Về bạn hoạt động chính bên trong phương thức oncreate thực hiện những điều sau đây. tại đây bạn đang tăng lượt xem của bạn với mapView

mapView = (MapView) findViewById(R.id.mapView); 
     LinearLayout zoomLayout = (LinearLayout)findViewById(R.id.zoom); 
     View zoomView = mapView.getZoomControls(); 

     zoomLayout.addView(zoomView, 
      new LinearLayout.LayoutParams(
       LayoutParams.WRAP_CONTENT, 
       LayoutParams.WRAP_CONTENT)); 
     mapView.displayZoomControls(true); 

.................................. ......................... Đây là cách bạn có thể sử dụng điều khiển thu phóng sẵn có của API ..

Bạn có thể có mã tùy chỉnh của riêng mình để thực hiện Phóng to và thu nhỏ như thế này ...

public boolean onKeyDown(int keyCode, KeyEvent event) 
{ 
    MapController mc = mapView.getController(); 
    switch (keyCode) 
    { 
     case KeyEvent.KEYCODE_3: 
      mc.zoomIn(); 
      break; 
     case KeyEvent.KEYCODE_1: 
      mc.zoomOut(); 
      break; 
    } 
    return super.onKeyDown(keyCode, event); 
}  

..This là làm thế nào tôi đã thực hiện ...

Thanks..Rakesh

25

Bạn có thể thực hiện "bỏ phiếu" cơ bản của riêng mình về giá trị thu phóng để phát hiện khi thu phóng đã được thay đổi bằng cách sử dụng android Handler.

Sử dụng mã sau cho sự kiện có thể chạy của bạn. Đây là nơi xử lý của bạn nên được thực hiện.

private Handler handler = new Handler(); 

public static final int zoomCheckingDelay = 500; // in ms 

private Runnable zoomChecker = new Runnable() 
{ 
    public void run() 
    { 
     checkMapIcons(); 

     handler.removeCallbacks(zoomChecker); // remove the old callback 
     handler.postDelayed(zoomChecker, zoomCheckingDelay); // register a new one 
    } 
}; 

Bắt đầu một sự kiện gọi lại sử dụng

protected void onResume() 
{ 
    super.onResume(); 
    handler.postDelayed(zoomChecker, zoomCheckingDelay); 
} 

dừng nó khi bạn rời khỏi hoạt động sử dụng

protected void onPause() 
{ 
    super.onPause(); 
    handler.removeCallbacks(zoomChecker); // stop the map from updating 
} 

Điều này được dựa trên có thể tìm thấy here nếu bạn muốn lâu hơn hãy viết ra giấy.

+1

Tôi đã trao phần thưởng cho câu trả lời này, bởi vì đây là cách đơn giản nhất để xác định xem bản đồ đã được di chuyển hay thu nhỏ chưa. –

1

Tôi đã sử dụng hỗn hợp ở trên. Tôi thấy rằng bằng cách sử dụng timmer để bắt đầu một chủ đề mỗi nửa thứ hai gây ra bản đồ để được thực sự jenky. Có lẽ bởi vì tôi đã sử dụng một vài bức thư Nếu mọi lúc. Vì vậy, tôi đã bắt đầu luồng trên bài đăng trễ 500ms từ onUserInteraction. Điều này cung cấp đủ thời gian cho zoomLevel để cập nhật trước khi thread bắt đầu chạy do đó nhận được zoomlevel chính xác mà không cần chạy một thread mỗi 500ms.

public void onUserInteraction() { 
    handler.postDelayed(zoomChecker, zoomCheckingDelay); 
} 
3

Tôi nghĩ có thể có câu trả lời khác cho câu hỏi này. Phương thức vẽ lớp phủ Lớp phủ được gọi sau khi thu phóng bất kỳ và tôi tin rằng điều này được gọi sau khi thay đổi mức thu phóng. Bạn có thể không kiến ​​trúc sư ứng dụng của bạn để tận dụng lợi thế này? Bạn thậm chí có thể sử dụng một lớp phủ giả chỉ để phát hiện điều này nếu bạn muốn. Điều này sẽ không hiệu quả hơn so với sử dụng một runnable với một sự chậm trễ?

@Override 
public boolean draw (Canvas canvas, MapView mapView, boolean shadow, long when) { 
    int zoomLevel = mapView.getZoomLevel(); 
    // do what you want with the zoom level 
    return super.draw(canvas, mapView, shadow, when); 
} 
4

Đây là giải pháp sạch. Chỉ cần thêm lớp riêng tư TouchOverlay này vào hoạt động của bạn và một phương thức được gọi là onZoom (được gọi bởi lớp bên trong này).

Lưu ý, bạn sẽ phải thêm TouchOverlay này vào bản đồ của mìnhXem ví dụ:

mapView.getOverlays().add(new TouchOverlay()); 

Nó theo dõi mức thu phóng bất cứ khi nào người dùng chạm vào bản đồ, ví dụ: để nhấn đúp hoặc chụm zoom và sau đó kích hoạt phương thức onZoom (với mức thu phóng) nếu mức thu phóng thay đổi.

private class TouchOverlay extends com.google.android.maps.Overlay { 
      int lastZoomLevel = -1; 

      @Override 
      public boolean onTouchEvent(MotionEvent event, MapView mapview) { 
       if (event.getAction() == 1) { 
        if (lastZoomLevel == -1) 
         lastZoomLevel = mapView.getZoomLevel(); 

        if (mapView.getZoomLevel() != lastZoomLevel) { 
         onZoom(mapView.getZoomLevel()); 
         lastZoomLevel = mapView.getZoomLevel(); 
        } 
       } 
       return false; 
      } 
     } 

     public void onZoom(int level) { 
      reloadMapData(); //act on zoom level change event here 
     } 
+0

Với giải pháp của bạn, tôi đã có thể dễ dàng nắm bắt các thay đổi thu phóng! Thx –

+0

Giải pháp Brilliant, tuy nhiên nó không phát hiện sự thay đổi đầu tiên trong zoom. Loại bỏ câu lệnh if đầu tiên cho -1 đã sửa lỗi này. – Aelexe

2

Đối với pre-V2.0, tôi đã thực hiện một lớp học kéo dài MapView rằng cảnh báo một người biết lắng nghe với sự kiện khi vùng bản đồ bắt đầu thay đổi (onRegionBeginChange) và ngừng thay đổi (onRegionEndChange).

import android.content.Context; 
import android.util.AttributeSet; 
import android.view.MotionEvent; 

import com.google.android.maps.GeoPoint; 
import com.google.android.maps.MapView; 

public class ExMapView extends MapView { 
    private static final String TAG = ExMapView.class.getSimpleName(); 
    private static final int DURATION_DEFAULT = 700; 

    private OnRegionChangedListener onRegionChangedListener; 
    private GeoPoint previousMapCenter; 
    private int previousZoomLevel; 
    private int changeDuration; // This is the duration between when the user stops moving the map around and when the onRegionEndChange event fires. 
    private boolean isTouched = false; 
    private boolean regionChanging = false; 

    private Runnable onRegionEndChangeTask = new Runnable() { 
     public void run() { 
      regionChanging = false; 
      previousMapCenter = getMapCenter(); 
      previousZoomLevel = getZoomLevel(); 
      if (onRegionChangedListener != null) { 
       onRegionChangedListener.onRegionEndChange(ExMapView.this, previousMapCenter, previousZoomLevel); 
      } 
     } 
    }; 

    public ExMapView(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     init(); 
    } 

    public ExMapView(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     init(); 
    } 

    public ExMapView(Context context, String apiKey) { 
     super(context, apiKey); 
     init(); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 
     isTouched = event.getAction() != MotionEvent.ACTION_UP; 
     return super.onTouchEvent(event); 
    } 

    @Override 
    public void computeScroll() { 
     super.computeScroll(); 

     // If the map region is still changing (user is still scrolling or zooming), reset timer for onRegionEndChange. 
     if ((!isTouched && !getMapCenter().equals(previousMapCenter)) || (previousZoomLevel != getZoomLevel())) { 

      // If the region has just begun changing, fire off onRegionBeginChange event. 
      if (!regionChanging) { 
       regionChanging = true; 
       if (onRegionChangedListener != null) { 
        onRegionChangedListener.onRegionBeginChange(this, previousMapCenter, previousZoomLevel); 
       } 
      } 

      // Reset timer for onRegionEndChange. 
      removeCallbacks(onRegionEndChangeTask); 
      postDelayed(onRegionEndChangeTask, changeDuration); 
     } 
    } 

    private void init() { 
     changeDuration = DURATION_DEFAULT; 
     previousMapCenter = getMapCenter(); 
     previousZoomLevel = getZoomLevel(); 
    } 

    public void setOnRegionChangedListener(OnRegionChangedListener listener) { 
     onRegionChangedListener = listener; 
    } 

    public void setChangeDuration(int duration) { 
     changeDuration = duration; 
    } 

    public interface OnRegionChangedListener { 
     public abstract void onRegionBeginChange(ExMapView exMapView, GeoPoint geoPoint, int zoomLevel); 
     public abstract void onRegionEndChange(ExMapView exMapView, GeoPoint geoPoint, int zoomLevel); 
    } 
} 
Các vấn đề liên quan