在上面的gif图像中,
1. 大家可以看到
(图不太好截取) 有个白色圆圈不断扩大,后又恢复原样的动画效果。
Marker动画效果
- Marker的帧动画
实现marker白色圆圈不断扩大后又恢复原样的效果
我们要先了解Marker的一些方法
请注意Marker还有一个 setIcon方法,与setIcons是有区别的。
MarkerOptions当然也有这些方法
其实实现这个效果有点像Android的帧动画。
但是这个没有停止动画的方法,如果需要停止marker的帧动画
那么我们就调用setIcon给Marker设置一张单个图片就可以了。
所以这个动画效果的开始与停止的代码如下:
/**
* 开启帧动画
* 设置多少帧刷新一次图片资源,Marker动画的间隔时间,值越小动画越快。默认为20,最小为1
*/
private void startFrameAnimation(@IntRange(from = 1, to = 20) int time) {
if (null != getMarker()) {
getMarker().setIcons(getListBitmapDescriptor());
// 设置多少帧刷新一次图片资源,Marker动画的间隔时间,值越小动画越快。默认为20,最小为1。
getMarker().setPeriod(time);
}
}
private void stopFrameAnimation() {
if (null != getMarker()) {
//设置单张图片效果 表示停止Marker帧动画
getMarker().setIcon(getSingleBitmapDescriptor());
}
}
在本篇的代码中 setIcons(List<> picList) picList 是根据一张图片生成的。主要用了
setXfermode这个特性来重新生成一张图片 如果你觉得麻烦其实也是可以用多张图片,这里我就不详细讲解了 看代码吧: 如果你觉得麻烦 就叫UI 给你几张图就可以了。下面是生成新图片的方法
public static Bitmap combineCenterBitmap(Bitmap background, float percent) {
if (background == null) {
return null;
}
int bgWidth = background.getWidth();
int bgHeight = background.getHeight();
int min = 5;
int max = bgWidth / 2;
int difference = max - min;
float radius = min + difference * percent + 1;
Bitmap newmap = Bitmap
.createBitmap(bgWidth, bgHeight, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(newmap);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.WHITE);
canvas.drawBitmap(background, 0, 0, paint);
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
canvas.drawCircle(bgWidth / 2, bgWidth / 2 + 1, radius, paint);
canvas.save(Canvas.ALL_SAVE_FLAG);
canvas.restore();
return newmap;
}
然后在代码中添加启动 停止动画的方法
public void hideCenterMarkerInfoWindow() {
centerMarker.hideInfoWindow();
stopFrameAnimation();
}
public void showLoadingInfoWindow() {
startFrameAnimation(5);
type = InfoWindowUIType.LOADING;
centerMarker.showInfoWindow();
}
public void showSuccessInfoWindow() {
stopFrameAnimation();
type = InfoWindowUIType.SUCCESS;
centerMarker.showInfoWindow();
}
public void showErrorInfoWindow() {
stopFrameAnimation();
type = InfoWindowUIType.FAILED;
centerMarker.showInfoWindow();
}
这样我们的marker就有帧动画的效果了
- Marker属性动画 (因为这个跟Android的属性动画很像,我们就取这个名字吧)
我们也可以完成其他动画 例如透明 旋转 移动 等。
其实这个跟Android本身动画差不多
不一样的是 Marker设置的动画类都是是高德自己实现的并不是Android自带的那些动画类。
现在我们来看下高德属性动画的实现方式
首先我们看marker的下面两个方法
高德自己实现的动画类有如下(跟Android的属性动画名称都一样 不要搞混了)
透明动画(AlphaAnimation)
旋转动画(RotateAnimation)
缩放动画(ScaleAnimation),
移动动画(TranslateAnimation)
动画集合(AnimationSet)
我们就以缩放动画为例来写代码:
//缩放动画
Animation scalAnimation = new ScaleAnimation(1F, 1F, 0.8F, 1F);
//时间设置短点
scalAnimation.setDuration(300);
centerMarker.setAnimation(scalAnimation);
centerMarker.startAnimation();
如何停止动画?
高德没提供停止的方法,不好意思我现在还没发现主动停止动画的方式。😶
动画还可以设置差值器等等其他,动画实现很多效果
添加代码如下:
/**
* 开启帧动画
* 设置多少帧刷新一次图片资源,Marker动画的间隔时间,值越小动画越快。默认为20,最小为1
*/
private void startFrameAnimation(@IntRange(from = 1, to = 20) int time) {
if (null != centerMarker) {
centerMarker.setIcons(getListBitmapDescriptor());
// 设置多少帧刷新一次图片资源,Marker动画的间隔时间,值越小动画越快。默认为20,最小为1。
centerMarker.setPeriod(time);
//缩放动画
Animation scalAnimation = new ScaleAnimation(1F, 1F, 0.8F, 1F);
//时间设置短点
scalAnimation.setDuration(300);
centerMarker.setAnimation(scalAnimation);
centerMarker.startAnimation();
}
}
那么完成如下效果:
逆地理编码
什么是逆地理编码: 这个名词 我第一次见觉得很深奥很难理解,后来觉得挺简单的, 其实这只是个名称,当我们知道他可以用来干什么,就非常好理解了。
逆地理编码 就是通过已知经纬度得到地址信息 例如:
104.053375,30.673637 这个是哪里呢 你总不能跟用户说经纬度是多少吧 所以我们可以使用逆地理编码得到 地址信息
步骤如下:
1. 逆地理编码(104.053375,30.673637)
2.得到结果 天府广场
3.那么你就可以跟用户说这里是天府广场
有逆地理编码 当然也有地理编码了。
简单来说
逆地理编码 是 《经纬度》 转换 《地址信息》
地理编码 是《地址信息》 转换 《经纬度》
官方解释:
地理编码又称地址匹配,指的是从已知的地址描述到对应的经纬 度坐标的转换
逆地理编码即地址解析服务,具体是指从已知的经纬度坐标到对 应的地址描述(如省市、街区、楼层、房间等)的转换。
GeocodeSearch 地理编码与逆地理编码类。
这个类既可以逆地理编码也可以地理编码。
看下这个类方法如下:
RegeocodeQuery
此类定义了逆地理编码查询的地理坐标点、查询范围、坐标类型。
我们看他的构造方法如下:
GeocodeSearch.OnGeocodeSearchListener
它回调方法如下:
逆地理编码实现代码:
private void startfindPointNameQuery(LatLonPoint point) {
//创建一个GeocodeSearch 逆地理编码和地理编码类
search = new GeocodeSearch(getContext());
//设置监听器
search.setOnGeocodeSearchListener(new GeocodeSearch.OnGeocodeSearchListener() {
@Override
public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int i) {
//逆地理编码异步返回
//由于我们的版本是大于3.2.1 所以成功是1000
if (i == 1000) {
//RegeocodeAddress是逆地理编码搜索的地理结果。
RegeocodeAddress regeocodeAddress = regeocodeResult.getRegeocodeAddress();
//逆地理编码返回的格式化地址。
String formatAddress = regeocodeAddress.getFormatAddress();
} else {
}
}
@Override
public void onGeocodeSearched(GeocodeResult geocodeResult, int i) {
//地理编码异步返回
}
});
//point - 要进行逆地理编码的地理坐标点。
//radius - 查找范围。默认值为1000,取值范围1-3000,单位米。
//latLonType - 输入参数坐标类型。包含GPS坐标和高德坐标。 GeocodeSearch.AMAP 、GeocodeSearch.GPS
float radius = 1000F;
//逆定力RegeocodeQuery构造函数
RegeocodeQuery regeocodeQuery = new RegeocodeQuery(point, radius, GeocodeSearch.AMAP);
//发起逆地理编码异步查询
search.getFromLocationAsyn(regeocodeQuery);
}
好了这样我们就可以获取到地址信息了
大家可以看到返回的onRegeocodeSearched方法的变量RegeocodeResult regeocodeResult
这个类最重要的方法 regeocodeResult.getRegeocodeAddress();
RegeocodeAddress
得到RegeocodeAddress 法包含了我们想要的信息formatAddress(地址信息) ,RegeocodeAddress类也有很多其他属性这里就不一一介绍了 请大家到高德的文档中查看吧:
好了 我们现在来 实现 获取中心marker坐标的 名称
我们添加UI效果,效果如下:
然后我们在获取地名成功后 设置TextView的文字就可以了
public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int i) {
//逆地理编码异步返回
//由于我们的版本是大于3.2.1 所以成功是1000
if (i == 1000) {
//RegeocodeAddress是逆地理编码搜索的地理结果。
RegeocodeAddress regeocodeAddress = regeocodeResult.getRegeocodeAddress();
//逆地理编码返回的格式化地址。
String formatAddress = regeocodeAddress.getFormatAddress();
centerMarkerView.showSuccessInfoWindow();
tv_start_place.setText(formatAddress);
} else {
centerMarkerView.showErrorInfoWindow();
tv_start_place.setText("获取位置失败");
}
}
然后我们实现附近车辆的效果。
附近车辆其实 多个marker 我们来实现这个效果
首先我们来看marker的设置角度的方法
MarkerOptions类:
Marker类:
然后我们设置marker的角度,
代码如下:
private void removeNearCarMarker() {
if (null != nearByCarMarkerList) {
for (Marker marker : nearByCarMarkerList) {
marker.remove();
}
}
}
private void addNearCarMarker(List<CarPositionData> list) {
nearByCarMarkerList = new ArrayList<>();
for (CarPositionData data : list) {
MarkerOptions markerOptions = new MarkerOptions();
markerOptions.icon(BitmapDescriptorFactory.fromResource(R.mipmap.car));
markerOptions.rotateAngle(data.getBearing());
LatLng latLng = new LatLng(data.getLatitude(), data.getLongitude());
markerOptions.position(latLng);
Marker marker = getAMap().addMarker(markerOptions);
nearByCarMarkerList.add(marker);
}
}
好了 我们通过方法产生附近的车辆数据(不用关心这个方法 在实际情况下应该是服务器返回给我们的)。
/**
* 获取模拟的附近的车辆的位置
*/
private void getNearCarFakeHttp(LatLonPoint point, final RegeocodeResult regeocodeResult) {
delayTest = new DelayTest();
delayTest.getDelayPost(point, new DelayTest.OnCallBack() {
@Override
public void onSuccess(List<CarPositionData> list) {
//RegeocodeAddress是逆地理编码搜索的地理结果。
RegeocodeAddress regeocodeAddress = regeocodeResult.getRegeocodeAddress();
//逆地理编码返回的格式化地址。
String formatAddress = regeocodeAddress.getFormatAddress();
//显示中心点marker成功的infoWindow
centerMarkerView.showSuccessInfoWindow();
//给定位的名称赋值到textView上
tv_start_place.setText(formatAddress);
//移除附近的车辆的marker
removeNearCarMarker();
//添加附近的车辆的marker
addNearCarMarker(list);
}
@Override
public void onFailed() {
//显示中心点失败的infoWindow
centerMarkerView.showErrorInfoWindow();
tv_start_place.setText("获取位置失败");
}
});
}
好了这样我们就完成了
(由于这个附近车辆的地理坐标是模拟产生的 所以车辆有可能不在道路,这个不是bug,如果是由真实车辆上传的,就不会有这个问题)
效果如下:
代码下载地址:gitee.com/justforgame…