真的是如何赶上地图平移和缩放完了吗? [英] How to catch that map panning and zoom are really finished?

查看:188
本文介绍了真的是如何赶上地图平移和缩放完了吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想写,将动态加载数据的映射,同时用户平移或缩放它的应用程序。

I am trying to write an application that will dynamically load data to map while user pans or zooms it.

我需要在地图上完成,以改变它的视图状态(停止平移或缩放),然后装入一个新的数据一部分,用于创建指标进行跟踪。但事实上,谷歌地图API没有任何事件来处理这个问题。

I need to track when the map is finished to change its view state (stops panning or zooming) and then load a new portion of data for creating markers. But in fact Google Maps API doesn't have any events to handle this.

有像创建一个空的覆盖控制 onTouch 事件等一些方法,但地图平移能持续多久之后用户完成了他的触摸,因为GMaps实现使用某种惯性使锅平滑。

There are some methods like creating an empty overlay to control onTouch events and so on, but map panning could last long after user finished his touch because GMaps use some kind of inertia to make the pan smoother.

我想继承图形页面画()方法最后因此不能被覆盖。

I tried to subclass MapView but its draw() method is final thus it cannot be overridden.

任何想法如何使平移和缩放整理precise处理?

Any ideas how to make precise handling of pan and zoom finishing?

推荐答案

研究的时间,有些决策被发现。它有一些缺点和优点,我会进一步说明。

Hours of researching and some decision was found. It has some cons and pros which I'll describe further.

我们应该做的主要事情是要忽略一些MapView类的方法来处理其绘图行为。在情况下,我们无法覆盖draw()方法,我们应该找到另一种方式还有另一个衍生的视图可以被覆盖 - computeScroll()方法。它被一再呼吁的地图继续填充。我们所要做的就是设置一些门槛的时间赶上如果computeScroll不叫了这个时候。
这是我做的:

The main thing we should do is to override some MapView's methods to handle its drawing behavior. In case we cannot override draw() method we should find another way in. There is another one derivative from View which may be overridden - computeScroll() method. It is called repeatedly as map continues padding. All we have to do is to set some time threshold to catch if computeScroll is not called anymore this time.
Here is what I did:

import java.util.Timer;
import java.util.TimerTask;

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 EnhancedMapView extends MapView {
public interface OnZoomChangeListener {
    public void onZoomChange(MapView view, int newZoom, int oldZoom);
}

public interface OnPanChangeListener {
    public void onPanChange(MapView view, GeoPoint newCenter, GeoPoint oldCenter);
}

private EnhancedMapView _this;

    // Set this variable to your preferred timeout
private long events_timeout = 500L;
private boolean is_touched = false;
private GeoPoint last_center_pos;
private int last_zoom;
private Timer zoom_event_delay_timer = new Timer();
private Timer pan_event_delay_timer = new Timer();

private EnhancedMapView.OnZoomChangeListener zoom_change_listener;
private EnhancedMapView.OnPanChangeListener pan_change_listener;


public EnhancedMapView(Context context, String apiKey) {
    super(context, apiKey);
    _this = this;
    last_center_pos = this.getMapCenter();
    last_zoom = this.getZoomLevel();
}

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

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

public void setOnZoomChangeListener(EnhancedMapView.OnZoomChangeListener l) {
    zoom_change_listener = l;
}

public void setOnPanChangeListener(EnhancedMapView.OnPanChangeListener l) {
    pan_change_listener = l;
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
    if (ev.getAction() == 1) {
        is_touched = false;
    } else {
        is_touched = true;
    }

    return super.onTouchEvent(ev);
}

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

    if (getZoomLevel() != last_zoom) {
                    // if computeScroll called before timer counts down we should drop it and start it over again
        zoom_event_delay_timer.cancel();
        zoom_event_delay_timer = new Timer();
        zoom_event_delay_timer.schedule(new TimerTask() {
            @Override
            public void run() {
                zoom_change_listener.onZoomChange(_this, getZoomLevel(), last_zoom);
                last_zoom = getZoomLevel();
            }
        }, events_timeout);
    }

    // Send event only when map's center has changed and user stopped touching the screen
    if (!last_center_pos.equals(getMapCenter()) || !is_touched) {
        pan_event_delay_timer.cancel();
        pan_event_delay_timer = new Timer();
        pan_event_delay_timer.schedule(new TimerTask() {
            @Override
            public void run() {
                pan_change_listener.onPanChange(_this, getMapCenter(), last_center_pos);
                last_center_pos = getMapCenter();
            }
        }, events_timeout);
    }
}

}

那么你应该在你的MapActivity这样的注册事件处理:

Then you should register event handlers in your MapActivity like this:

public class YourMapActivity extends MapActivity {

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mv = new EnhancedMapView(this, "<your Maps API key here>");

    mv.setClickable(true);
    mv.setBuiltInZoomControls(true);

    mv.setOnZoomChangeListener(new EnhancedMapView.OnZoomChangeListener() {
        @Override
        public void onZoomChange(MapView view, int newZoom, int oldZoom) {
            Log.d("test", "zoom changed from " + oldZoom + " to " + newZoom);
        }
    }
    mv.setOnPanChangeListener(new EnhancedMapView.OnPanChangeListener() {
        public void onPanChange(MapView view, GeoPoint newCenter, GeoPoint oldCenter) {
            Log.d("test", "center changed from " + oldCenter.getLatitudeE6() + "," + oldCenter.getLongitudeE6() + " to " + newCenter.getLatitudeE6() + "," + newCenter.getLongitudeE6());
        }
    }
}

现在怎么样这种方法的优点和缺点?
优点:
- 事件处理无论哪种方式,地图是平移或缩放。触摸事件,使用硬件密钥,甚至编程解雇事件的处理(如setZoom()或动画()方法)。
- 能够跳过不必要的数据加载,如果用户点击快速放大按钮几次。事件只会发生火灾后点击停止。
缺点:
- 这是很不可能取消缩放或平移动作(也许我会添加这种能力在未来)

Now what about advantages and disadvantages of this approach?
Advantages:
- Events handles either way map was panned or zoomed. Touch event, hardware keys used, even programmatically fired events are handled (like setZoom() or animate() methods).
- Ability to skip unnecessary loading of data if user clicks zoom button several times quickly. Event will fire only after clicks will stop.
Disadvantages:
- It is quite not possible to cancel zooming or panning action (maybe I'll add this ability in the future)

希望这个小课程将帮助你。

Hope this little class will help you.

这篇关于真的是如何赶上地图平移和缩放完了吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆