Android 如何捕捉到地图平移和缩放真的完成了?
我正在尝试编写一个应用程序,当用户平移或缩放数据时,它将动态加载数据到地图 我需要跟踪地图何时完成以更改其视图状态(停止平移或缩放),然后加载用于创建标记的新数据部分。但事实上谷歌地图API并没有任何事件来处理这个问题 有一些方法,比如创建一个空覆盖来控制触摸事件等等,但是地图平移可能会在用户完成触摸后持续很长时间,因为GMAP使用某种惯性使平移更平滑 我试图将Android 如何捕捉到地图平移和缩放真的完成了?,android,google-maps,drag,dynamic-data,Android,Google Maps,Drag,Dynamic Data,我正在尝试编写一个应用程序,当用户平移或缩放数据时,它将动态加载数据到地图 我需要跟踪地图何时完成以更改其视图状态(停止平移或缩放),然后加载用于创建标记的新数据部分。但事实上谷歌地图API并没有任何事件来处理这个问题 有一些方法,比如创建一个空覆盖来控制触摸事件等等,但是地图平移可能会在用户完成触摸后持续很长时间,因为GMAP使用某种惯性使平移更平滑 我试图将MapView子类化,但是它的draw()方法是final,因此无法重写它 有没有关于如何精确处理平移和变焦整理的想法?经过数小时的研究
MapView
子类化,但是它的draw()
方法是final
,因此无法重写它
有没有关于如何精确处理平移和变焦整理的想法?经过数小时的研究和决定,终于找到了答案。它有一些缺点和优点,我将进一步描述 我们应该做的主要事情是重写某些MapView的方法来处理其绘图行为。如果我们不能重写draw()方法,我们应该在中找到另一种方法。还有另一个来自视图的派生,可能会被覆盖-computeScroll()方法。当map继续填充时,会重复调用它。如果这次不再调用computeScroll,我们所要做的就是设置一些时间阈值来捕获。
以下是我所做的:
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中注册事件处理程序,如下所示:
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());
}
}
}
公共类YourMapActivity扩展了MapActivity{
@凌驾
创建时的公共void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
mv=新的EnhancedMapView(此“”);
mv.可设置可点击(真);
mv.SetBuiltinzoomControl(真);
mv.setOnZoomChangeListener(新增强的MapView.OnZoomChangeListener(){
@凌驾
public void onZoomChange(地图视图、int-newZoom、int-oldZoom){
Log.d(“测试”,“缩放从“+oldZoom+”更改为“+newZoom”);
}
}
mv.setOnPanChangeListener(新的增强MapView.OnPanChangeListener(){
公共无效onPanChange(地图视图、地质点新中心、地质点旧中心){
Log.d(“测试”,“中心从“+oldCenter.getLatitudeE6()+”,“+oldCenter.getLongitudeE6()+”更改为“+newCenter.getLatitudeE6()+”,“+newCenter.getLongitudeE6()”);
}
}
}
现在,这种方法的优缺点是什么?优点:
-事件处理地图平移或缩放的方式。触摸事件、使用的硬件键,甚至程序触发的事件都会被处理(如setZoom()或animate()方法)。
-如果用户快速多次单击缩放按钮,可以跳过不必要的数据加载。只有在单击停止后,事件才会触发。
缺点:
-取消缩放或平移操作是不可能的(也许我以后会添加这个功能) 希望这个小班能对你有所帮助。这个项目最初发布在a上,帮助我完成了你要求的相同任务。现在可以使用:
googleMap.setOnCameraIdleListener {
//Do your thing
}
相机移动结束时的回调接口使用此解决方案时我注意到的另一个小问题是,更改我的一个
OverlayItem
s的可绘制项或更改旋转,computeScroll()也会被触发,使onPanChangeListener启动。不是所有的类构造函数都会初始化内部结构,比如这个,最后一个中心位置,最后一个缩放。据我所知,它们应该。(!最后一个中心位置等于(getMapCenter())| |!被触摸)应该是(!最后一个中心位置等于(getMapCenter())&!被触摸)否则,当用户不触摸屏幕时,平移监听器会持续激发。您在该行上方的注释中使用了“and”来描述条件。我创建了一个小的MapView类,它有三个事件,onClick、onPan和onZoom。我看到他们使用了我的技术。也许他们甚至受到了我的回答的启发不管怎样,我很感激有人把它作为一个独立的图书馆。