在不少应用中都Marker在地图控件中间位置不变化:以下图java
ps:有人说是屏幕这个其实形容不许确 实际上是MapView的中心点,只不过地图通常都是铺满屏幕的,因此才会有屏幕的说法android
请注意:(在这篇文章中 屏幕指MapView)git
在上一期中 咱们知道 Marker类有 设置Marker像素位置的方法以下markdown
那么咱们如何取的地图控件中心点的像素坐标呢。网络
这里咱们须要了解两个新的类框架
相机位置,这个类包含了全部的可视区域的位置参数。dom
这个类是咱们在地图移动视角后,存储一些参数以下:ide
在这个类中 target属性是地图控件中心点的坐标,这个是属性是咱们等会要使用oop
这个类负责将屏幕位置和地理坐标(经纬度)进行转换。屏幕位置是相对地图的左上角的位置,因此并不必定是从整个屏幕开始计算的。学习
这个类重要的是他的方法。请看以下图
看完上面咱们就应该知道 若是取地图控件中心点的像素位置了。
咱们要经过CarmeraPositon的target属性要拿到地图中心点的坐标
经过Projection的toScreenLocation方法来获取地图控件中心点的像素位置
代码以下:
//拿到地图中心点的坐标。
LatLng latLng = aMap.getCameraPosition().target;
//把中心点的坐标转换成屏幕像素位置
Point screenPosition = aMap.getProjection().toScreenLocation(latLng);
//给marker设置像素位置。
marker.setPositionByPixels(screenPosition.x, screenPosition.y);
复制代码
调用这段代码须要注意的问题:
若是咱们直接在Activty中的onCreate或者Frgment的onViewCreate方法调用,因为MapView这个时候的长度和宽度都仍是0,这个时候算出的screenPosition.x screenPosition.y
都为0.计算的结果是不正确的,你会看不到Marker的,
因此咱们要在MapView的长度和宽度已经算出来的状况下在调用这个方法,
高德SDK也提供了这个方法代码以下:
getAMap().setOnMapLoadedListener(new AMap.OnMapLoadedListener() {
@Override
public void onMapLoaded() {
//在这里调用这个方法,才能显示出来
addCenterMarker();
}
});
复制代码
好了 咱们来实现下面的这个效果
首先咱们分析下这个功能,
1. 移动地图的时候 infoWindow隐藏,
2. 中止移动的时候 infoWindow显示loading效果。
3. 根据坐标的获取地理名称后 infoWindow显示成功。 固然也有失败的状况。
根据坐标点的获取地理名称 在高德上 叫逆地理编码, 是一个耗时操做(至关于一个网络请求)
ps: 你们看到那个三分钟和附近车辆的坐标位置, 其实应该是滴滴网络请求接口返回的,可是我并无这个接口 就直接写了 3分钟,附近车辆坐标是根据坐标点随机生成。
固然在实际状况下这样确定不行 正常状况应该是:
当咱们中止移动地图的时候,应该有两个耗时操做,一个是获取坐标点地理名称(逆地理编码),一个是获取预估时间附近车辆位置(http请求接口),且这两个耗时操做都要成功 InfoWindow 才能显示成功。
这个时候我就很是推荐使用RXJAVA来实现这个功能了。
可是是在这里咱们主要是介绍高德SDK 尽可能不引入其余框架,来增长你们的学习成本。
在代码中我会作一个测试数据来模拟获取预估时间附近车辆位置(http请求接口) 不使用rxjava
首先咱们了解下 一个方法
OnCameraChangeListener:
这个方法会在地图移动的时候回调。
onCameraChange 会在移动地图的时候不断调用
onCameraChangeFinish 会在地图中止移动的时候的调用
复制代码
咱们应该
在onCameraChange 隐藏infoWindow
在onCameraChangeFinish 进行逆地理编码和获取接驾时间的耗时操做,infoWindow同时显示loading效果,成功后infoWindow显示成功 失败后InfoWindow显示失败
咱们把代码都写在Fragment中很差 因此咱们封装一下
建一个CenterMarkerView类
复制代码
代码以下:
/**
* @author jikun
* Created by jikun on 2018/3/14.
*/
public class CenterMarkerView {
private Marker centerMarker;
public void addCenterMarker(AMap aMap) {
MarkerOptions options = new MarkerOptions();
//对应Marker.setIcon方法 设置Marker的图片
options.icon(BitmapDescriptorFactory.fromResource(R.mipmap.icon_me_location));
options.anchor(0.5F, 1);
//拿到地图中心点的坐标。
LatLng latLng = aMap.getCameraPosition().target;
//把中心点的坐标转换成屏幕像素位置
Point screenPosition = aMap.getProjection().toScreenLocation(latLng);
//在地图上添加Marker并获取到Marker.
centerMarker = aMap.addMarker(options);
//给marker设置像素位置。
centerMarker.setPositionByPixels(screenPosition.x, screenPosition.y);
centerMarker.setAnchor(0.5F, 1);
}
public void initInfoWindowsView(final Context context, AMap aMap) {
aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() {
@Override
public View getInfoWindow(Marker marker) {
View infoWindow = LayoutInflater.from(context).inflate(
R.layout.map_fast_car_info_window, null);
infoWindow.findViewById(R.id.ll_have_net).setVisibility(View.VISIBLE);
infoWindow.findViewById(R.id.ll_no_net).setVisibility(View.GONE);
infoWindow.findViewById(R.id.ll_left).setVisibility(View.VISIBLE);
infoWindow.findViewById(R.id.iv_loading).setVisibility(View.GONE);
return infoWindow;
}
@Override
public View getInfoContents(Marker marker) {
return null;
}
});
}
public void hideCenterMarkerInfoWindow() {
}
public void showLoadingInfoWindow() {
}
public void showSuccessInfoWindow() {
}
public void showErrorInfoWindow() {
}
public void destorty() {
if (null != centerMarker) {
centerMarker.destroy();
}
}
}
复制代码
当咱们调用Marker.showInfoWindow 方法的时候 InfoWindowAdapter的getInfoWindow()和getInfoContents()会回调
根据这个 咱们先写一个枚举类 来区分当前InfoWindow是 加载中 仍是成功 或者失败的UI效果
注解代码以下:
//添加支持注解的依赖到你的项目中,须要在build.gradle文件中的依赖块中添加:
//dependencies { compile 'com.android.support:support-annotations:24.2.0' }
@IntDef({InfoWindowUIType.LOADING, InfoWindowUIType.SUCCESS, InfoWindowUIType.FAILED})
@Retention(RetentionPolicy.SOURCE)
public @interface InfoWindowUIType {
public static final int LOADING = 0;
public static final int SUCCESS = 1;
public static final int FAILED = 2;
}
复制代码
好了咱们来写UI控制效果 代码以下:
public void initInfoWindowsView(final Context context, AMap aMap) {
aMap.setInfoWindowAdapter(new AMap.InfoWindowAdapter() {
@Override
public View getInfoWindow(Marker marker) {
View infoWindow = LayoutInflater.from(context).inflate(
R.layout.map_fast_car_info_window, null);
switch (type) {
case InfoWindowUIType.LOADING:
//Loading InfoWindow显示效果
infoWindow.findViewById(R.id.ll_have_net).setVisibility(View.VISIBLE);
infoWindow.findViewById(R.id.ll_no_net).setVisibility(View.GONE);
infoWindow.findViewById(R.id.ll_left).setVisibility(View.GONE);
infoWindow.findViewById(R.id.iv_loading).setVisibility(View.VISIBLE);
ImageView imageView = infoWindow.findViewById(R.id.iv_loading);
AnimationDrawable animationDrawable = (AnimationDrawable) imageView.getDrawable();
if (!animationDrawable.isRunning()) {
animationDrawable.start();
}
break;
case InfoWindowUIType.SUCCESS:
infoWindow.findViewById(R.id.ll_have_net).setVisibility(View.VISIBLE);
infoWindow.findViewById(R.id.ll_no_net).setVisibility(View.GONE);
infoWindow.findViewById(R.id.ll_left).setVisibility(View.VISIBLE);
infoWindow.findViewById(R.id.iv_loading).setVisibility(View.GONE);
break;
case InfoWindowUIType.FAILED:
infoWindow.findViewById(R.id.ll_have_net).setVisibility(View.GONE);
infoWindow.findViewById(R.id.ll_no_net).setVisibility(View.VISIBLE);
break;
default:
break;
}
return infoWindow;
}
@Override
public View getInfoContents(Marker marker) {
return null;
}
});
}
复制代码
咱们添加一个模拟请求的延迟类
代码以下
/**
* @author jikun
* Created by jikun on 2018/3/14.
*/
public class DelayTest {
public OnCallBack callBack;
public Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (null != callBack) {
callBack.onSuccess();
}
}
};
public void getDelayPost(OnCallBack callBack) {
this.callBack = callBack;
long sec = (long) (Math.random() * 1300);
Log.e("测试代码", "测试代码时间=" + sec);
handler.sendEmptyMessageDelayed(0, sec);
}
public void stop() {
this.callBack = null;
}
public interface OnCallBack {
void onSuccess();
void onFailed();
}
public void destory() {
handler.removeCallbacksAndMessages(null);
}
}
复制代码
而后在CenterMarkerMapFragment 的代码以下:
/**
* @author jikun
* Created by jikun on 2018/3/13.
*/
public class CenterMarkerMapFragment extends BaseMapFragment {
private CenterMarkerView centerMarkerView;
private DelayTest delayTest;
public static CenterMarkerMapFragment newInstance() {
Bundle args = new Bundle();
CenterMarkerMapFragment fragment = new CenterMarkerMapFragment();
fragment.setArguments(args);
return fragment;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_marker_map, container, false);
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
TextureMapView textureMapView = view.findViewById(R.id.textureMapView);
delayTest = new DelayTest();
initMapView(textureMapView, savedInstanceState);
centerMarkerView = new CenterMarkerView();
centerMarkerView.initInfoWindowsView(getContext(), getAMap());
getAMap().setOnMapLoadedListener(new AMap.OnMapLoadedListener() {
@Override
public void onMapLoaded() {
centerMarkerView.addCenterMarker(getAMap());
moveCameraOnMap();
}
});
getAMap().setOnCameraChangeListener(new AMap.OnCameraChangeListener() {
@Override
public void onCameraChange(CameraPosition cameraPosition) {
delayTest.stop();
centerMarkerView.hideCenterMarkerInfoWindow();
}
@Override
public void onCameraChangeFinish(CameraPosition cameraPosition) {
centerMarkerView.showLoadingInfoWindow();
delayTest.getDelayPost(new DelayTest.OnCallBack() {
@Override
public void onSuccess() {
centerMarkerView.showSuccessInfoWindow();
}
@Override
public void onFailed() {
centerMarkerView.showErrorInfoWindow();
}
});
}
});
}
@Override
public void onDestroy() {
super.onDestroy();
centerMarkerView.destorty();
delayTest.destory();
}
/**
* 移动地图到Marker标记点位置的方法。
*/
private void moveCameraOnMap() {
LatLng latLng = new LatLng(30.657505, 104.065692);
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLng(latLng);
getAMap().moveCamera(cameraUpdate);
}
复制代码
最后咱们就实现以下效果
因为篇幅问题,
逆地理编码和 显示周围车辆我就放在下一篇中讲解了。
代码下载地址:gitee.com/justforgame…