Android高德SDK 地图篇三:Marker实现选择起点

在不少应用中都Marker在地图控件中间位置不变化:以下图java

ps:有人说是屏幕这个其实形容不许确 实际上是MapView的中心点,只不过地图通常都是铺满屏幕的,因此才会有屏幕的说法android

请注意:(在这篇文章中 屏幕指MapView)git

在上一期中 咱们知道 Marker类有   设置Marker像素位置的方法以下markdown

那么咱们如何取的地图控件中心点的像素坐标呢。网络

这里咱们须要了解两个新的类框架

  • CameraPosition

   相机位置,这个类包含了全部的可视区域的位置参数。dom

  这个类是咱们在地图移动视角后,存储一些参数以下:ide

在这个类中 target属性是地图控件中心点的坐标,这个是属性是咱们等会要使用oop

  • Projection 

这个类负责将屏幕位置和地理坐标(经纬度)进行转换。屏幕位置是相对地图的左上角的位置,因此并不必定是从整个屏幕开始计算的。学习

这个类重要的是他的方法。请看以下图

看完上面咱们就应该知道 若是取地图控件中心点的像素位置了。

咱们要经过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();
    }
});
复制代码

移动地图后获取中间Marker的坐标点(实现选择起点)

好了 咱们来实现下面的这个效果

首先咱们分析下这个功能,

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…

相关文章
相关标签/搜索