Android gaode高德地图小人运动轨迹动态移动handler实现,不同于官网的平滑移动,可以控制速度、地图缩放、跟随小人移动后续生成视频,类似华为运动

package com.example.tsdemo;

import android.app.Activity;
import android.os.Handler;
import android.os.Looper;

import java.util.ArrayList;
import android.app.Activity;
import android.os.Handler;
import android.os.Looper;
import android.util.Pair;
import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.CustomRenderer;
import com.amap.api.maps.MapView;
import com.amap.api.maps.UiSettings;
import com.amap.api.maps.model.BitmapDescriptor;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.LatLngBounds;
import com.amap.api.maps.model.MyLocationStyle;
import com.amap.api.maps.model.PolylineOptions;


import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;

public class RecordAMapHelper {
    private Activity activity;
    private AMap mAMap;
    private MapView mapView;
    private UiSettings uiSettings;
    private PolylineOptions mPolylineOptions;//画线
    private PathSmoothTool mpathSmoothTool;//平滑处理工具 官网下载
    private final int maxZoomLevel = 16;//最大缩放  23最大 1最小
    private int currentIndex;
    private Handler handler = new Handler(Looper.getMainLooper());
    private final List<LatLng> resultList = new ArrayList<>();//数据过滤的时候 需要注意
    private Marker tagMarker;
    private List<LatLng> mLatLngLists = new ArrayList<>();
    private List<LatLng> mLatLngLists_move = new ArrayList<>();

    public RecordAMapHelper(MapView mapView, Activity activity) {
        this.mapView = mapView;
        this.activity = activity;
        setMapSetting();
        setUpMap();
        currentIndex = 0;
    }

    private void setMapSetting() {
        mAMap = mapView.getMap();
        mAMap.setMapType(AMap.MAP_TYPE_SATELLITE)
        mAMap.setMaxZoomLevel(maxZoomLevel);
        mAMap.setMapTextZIndex(2);
        mapView.getMap().moveCamera(CameraUpdateFactory.zoomTo(maxZoomLevel))
        setMapUiSetting();
    }

    private void setMapUiSetting() {
        uiSettings = mAMap.getUiSettings();
        uiSettings.setMyLocationButtonEnabled(false);// 设置默认定位按钮是否显示
        uiSettings.setZoomControlsEnabled(false);// 设置默认缩放按钮是否显示
        uiSettings.setCompassEnabled(false);// 设置默认指南针是否显示
    }

    public void setmLatLngLists(List<LatLng> mLatLngLists) {
        this.mLatLngLists.addAll(mLatLngLists);
    }

    public void addmLatLngLists_move(List<LatLng> mLatLngLists_move) {
        this.mLatLngLists_move.addAll(mLatLngLists_move);
    }

    private void setUpMap() {
        if (mAMap == null) {
            mAMap = mapView.getMap();
        }
        mpathSmoothTool = new PathSmoothTool();
        mpathSmoothTool.setIntensity(5);
    }

    private PolylineOptions initPolyline(List<LatLng> resultList) {
        mPolylineOptions = new PolylineOptions();
        mPolylineOptions.color(0xff13E57B);
        mPolylineOptions.width(10f);
        mPolylineOptions.useGradient(false);
        mPolylineOptions.addAll(resultList);
        mPolylineOptions.setEraseColor(true, 0xffffffff);
        return mPolylineOptions;
    }

    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            activity.runOnUiThread(() -> {
                //提升加载速度的话   设置currentIndex的值   结束了以后移除runner
                if (currentIndex >= mLatLngLists.size()) {
                    handler.removeCallbacks(runnable);
                    handler.postDelayed(completeRunnable, 1000);
//走到最后一个点位的时候  移除小人显示  终点图标
                    if (tagMarker != null) {
                        tagMarker.remove();
                    }
                    if (resultList.size() > 1) {
                        mAMap.addMarker(new MarkerOptions()
                                .icon(getIconBitmap(1))
                                .position(mLatLngLists.get(mLatLngLists.size() - 1)));
                    }
                } else {
                    resultList.add(mLatLngLists.get(currentIndex));
                    currentIndex = currentIndex + 2;//循环获取➕2数据  可以过滤 +1  +2 +3
                    PolylineOptions options = initPolyline(resultList);//画线 每次进来数据都会++
                    mAMap.addPolyline(options);//添加到地图
                    tagMarker.setPosition(resultList.get(resultList.size() - 1));//小人的图标
//animateCamera 需要250毫秒才刷新一次
                    if (currentIndex % 50 == 0) {
                        mAMap.animateCamera(CameraUpdateFactory.newLatLngZoom(resultList.get(resultList.size() - 1), maxZoomLevel));
                    }

                    handler.postDelayed(this, 20);
                }
            });
        }
    };

    Runnable completeRunnable = new Runnable() {
        @Override
        public void run() {
            activity.runOnUiThread(() -> {
                setMapZoom(mLatLngLists);
            });
        }
    };

    private void setStartEndPoint() {
// 增加起点开始
        mAMap.addMarker(new MarkerOptions()
                .icon(getIconBitmap(0))
                .position(mLatLngLists.get(0))
        );
        MarkerOptions option = new MarkerOptions();
        option.anchor(0.5f, 0.5f)
                .icon(getIconBitmapTag())
                .position(mLatLngLists.get(0));
        tagMarker = mAMap.addMarker(option);
    }

    public void destroyAll() {
        handler.removeCallbacks(runnable);
        handler.removeCallbacks(completeRunnable);
        handler = null;
    }

    public BitmapDescriptor getIconBitmap(int type) {
        if (type == 1) {
            return BitmapDescriptorFactory.fromResource(R.mipmap.ic_sport_end);
        } else {
            return BitmapDescriptorFactory.fromResource(R.mipmap.ic_sport_start);
        }
    }

    public BitmapDescriptor getIconBitmapTag() {
        return BitmapDescriptorFactory.fromResource(R.mipmap.ic_sport_tag);
    }


    //在地图上添加本地轨迹数据,并处理
    public void addLocpath() {
        if (mLatLngLists == null || mLatLngLists.isEmpty()) {
            return;
        }
        handler.postDelayed(runnable, 20);
//增加起点
        setStartEndPoint();
        mAMap.animateCamera(CameraUpdateFactory.newLatLngZoom(mLatLngLists.get(0), maxZoomLevel));
    }

    //路线小人  平滑移动 官网上有   比自己写更加流畅  官网有的代码
    public void moveMarker() {
        LatLng latLngStart = mLatLngLists_move.get(0);
        SmoothMoveMarker smoothMarker = new SmoothMoveMarker(mAMap);
        smoothMarker.setDescriptor(BitmapDescriptorFactory.fromResource(R.mipmap.ic_sport_tag));
        Pair<Integer, LatLng> pair = SpatialRelationUtil.calShortestDistancePoint(mLatLngLists_move, latLngStart);
        mLatLngLists_move.set(pair.first, latLngStart);
        List<LatLng> subList = mLatLngLists_move.subList(pair.first, mLatLngLists_move.size());
        smoothMarker.setPoints(subList);
        smoothMarker.startSmoothMove();
    }

    //newLatLngBounds  第二个参数  200 越大 显示的范围越大
    public void setMapZoom(List<LatLng> latLngLists) {
        if (latLngLists != null && latLngLists.size() > 1) {
            LatLngBounds.Builder b = LatLngBounds.builder();
            for (LatLng latLngList : latLngLists) {
                b.include(latLngList);
            }
            LatLngBounds bounds = b.build();
            mAMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 150));
        } else {
            LogUtil.e("缩放数据的大小小于1.....");
        }

    }
}

//    use:
//    private ArrayList<LatLng> sportGPSData = new ArrayList<>();
//    aMapHelper = new RecordAMapHelper(mapView, getActivity());
//aMapHelper.setmLatLngLists(sportGPSData);
//aMapHelper.addmLatLngLists_move(sportGPSData);
//aMapHelper.addLocpath();

1.使用handler  post方法控制小人移动的速度

2.高德地图中animateCamera 跟其他移动到中心点的方法不太一样 注意,其中一个直接写地图缩放等级用的比较多  还有  bound  设置200这种  用法不一样看你自己需要

3.官网提供的轨迹平滑移动会过滤掉很多点坐标,不建议使用

4.在app切换到后台的时候  无法准确获取到定位坐标,会导致在路线绘制的时候一跳一跳的 ,或者本身定位的时候差异 在50米以上的时候 也会出现,目前暂时未解决,只有应用一直在前台的时候才不会出现该问题

5.在运动的时候通过他官网的计算两个点距离的方法过滤掉小于1.5米的会更加准确

6.计算运动移动的距离的时候如果是通过点坐标来计算获得的话 ,后面再绘制路线的时候更好把控,不然加业务需求的时候无法精准计算他的运动时间 还有每一公里的数值,导致计算不准确

7.定义成工具类不好操作ui页面,

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值