高德地图SDK Android版开发 8 覆盖物示例2动画
前言
前文介绍了高德地图Marker
支持多种动画类型:
帧动画; Animation
动画(包括平移、旋转、透明、缩放和组合动画)。
本文重点介绍Marker
动画相关的类和接口,以及示例代码。
动画相关的类和接口
帧动画
帧动画 的功能通过MarkerOptions
类来设置,一次传入一个Icon列表,通过period
设定刷新的帧间隔。
MarkerOptions
类型 方法 说明 MarkerOptions icons
(ArrayList< BitmapDescriptor > icons)设置Marker覆盖物的动画帧图标列表,多张图片模拟gif的效果。 MarkerOptions period
(int period)设置多少帧刷新一次图片资源,Marker动画的间隔时间,值越小动画越快。
Animation动画
Marker还支持设置旋转、缩放、平移、透明和组合动画效果 。通过Marker类setAnimation方法设置。
类 说明 说明 void setAnimation
(Animation animation)设置动画。动画包含,旋转,缩放,消失,平移以及它们的组合动画 boolean startAnimation
()开始动画
Animation类及其子类
动画类别 类 说明 抽象类 Animation
动画,可用于支持动画的覆盖物。使用方法如同Android系统自带的Animation 移动动画 TranslateAnimation
控制移动的动画类 旋转动画 RotateAnimation
控制旋转的动画类 透明度动画 AlphaAnimation
控制透明度的动画类 缩放动画 ScaleAnimation
控制缩放的动画类 组合动画 AnimationSet
动画集合
TranslateAnimation
+TranslateAnimation(latLng)
#String getAnimationType()
Animation
+int getFillMode()
+int getRepeatCount()
+int getRepeatMode()
+void setAnimationListener(listener)
+void setDuration(duration)
+void setFillMode(fillMode)
+void setInterpolator(interpolator)
+void setRepeatCount(repeatCount)
+void setRepeatMode(repeatMode)
RotateAnimation
+RotateAnimation(fromdegree, todegree)
#String getAnimationType()
AlphaAnimation
+AlphaAnimation(fromAlpha, toAlpha)
#String getAnimationType()
ScaleAnimation
+ScaleAnimation(fromX, toX, fromY, toY)
#String getAnimationType()
AnimationSet
+AnimationSet(shareInterpolator)
+void addAnimation(animation)
+void cleanAnimation()
#String getAnimationType()
Animation
类 说明 说明 int getFillMode
()获取动画执行完成后的状态 int getRepeatCount
()获取动画重复执行的次数 int getRepeatMode
()重复执行的模式 void setAnimationListener
(Animation.AnimationListener listener)设置动画监听器 void setDuration
(long duration)设置动画持续时间。如果设置为负数,会修正为0 void setFillMode
(int fillMode)设置动画执行完成后的状态。默认FILL_MODE_FORWARDS
void setInterpolator
(Interpolator interpolator)设置插值器。默认是线性插值器 void setRepeatCount
(int repeatCount)设置动画重复执行的次数。默认为0 void setRepeatMode
(int repeatMode)重复执行的模式。默认RESTART
类型 常量 说明 static int FILL_MODE_BACKWARDS
动画执行后保持在第一帧 static int FILL_MODE_FORWARDS
动画执行后保持在最后一帧 static int INFINITE
无限期地重复动画 static int RESTART
动画结束后从头播放,最大重复次数受Animation.setRepeatCount(int) 限制 static int REVERSE
动画结束后从尾倒放,最大重复次数受Animation.setRepeatCount(int) 限制
animation. setRepeatMode ( Animation . RESTART ) ;
animation. setFillMode ( Animation . FILL_MODE_BACKWARDS ) ;
animation. setRepeatCount ( Animation . INFINITE ) ;
public interface AnimationListener {
void onAnimationStart ( ) ;
void onAnimationEnd ( ) ;
}
TranslateAnimation
类 说明 说明 TranslateAnimation
(LatLng target)控制移动的动画类 protected String getAnimationType
()
RotateAnimation
类 说明 说明 RotateAnimation
(float fromdegree, float todegree)控制旋转的动画类 protected String getAnimationType
()
AlphaAnimation
类 说明 说明 AlphaAnimation
(float fromAlpha, float toAlpha)控制透明度的动画类。 透明度范围[0,1], 1为不透明 protected String getAnimationType
()
ScaleAnimation
类 说明 说明 ScaleAnimation
(float fromX, float toX, float fromY, float toY)控制缩放的动画类。 比如要实现一个Marker生长动画,可以使用 (0,1,0,1) protected String getAnimationType
()
AnimationSet
类 说明 说明 AnimationSet
(boolean shareInterpolator)动画集合 void addAnimation
(Animation animation)添加动画 void cleanAnimation
()清除动画 protected String getAnimationType
()
Marker动画示例
本示例包括帧动画、Animation动画,以及官方Demo中的生长、跳跃和呼吸动画。
界面布局
<?xml version="1.0" encoding="utf-8"?>
< androidx.constraintlayout.widget.ConstraintLayout xmlns: android= " http://schemas.android.com/apk/res/android"
xmlns: app= " http://schemas.android.com/apk/res-auto"
xmlns: tools= " http://schemas.android.com/tools"
android: layout_width= " match_parent"
android: layout_height= " match_parent"
tools: context= " .MapMarkerAnimationActivity" >
< com.amap.api.maps.MapView
android: id= " @+id/map"
android: layout_width= " match_parent"
android: layout_height= " 0dp"
app: layout_constraintBottom_toTopOf= " @id/bottomView"
app: layout_constraintTop_toTopOf= " parent" />
< androidx.appcompat.widget.LinearLayoutCompat
android: id= " @+id/bottomView"
android: layout_width= " match_parent"
android: layout_height= " wrap_content"
android: orientation= " vertical"
app: layout_constraintBottom_toBottomOf= " parent"
app: layout_constraintTop_toBottomOf= " @id/map" >
< RadioGroup
android: id= " @+id/RadioGroup"
android: layout_width= " match_parent"
android: layout_height= " wrap_content"
android: background= " @android:color/background_dark"
android: gravity= " center_horizontal"
android: orientation= " horizontal"
android: paddingHorizontal= " 10dp" >
< RadioButton
android: id= " @+id/frameAnimation"
android: layout_width= " 0dp"
android: layout_height= " wrap_content"
android: layout_weight= " 1"
android: checked= " true"
android: onClick= " setAnimationFlag"
android: text= " 帧动画"
android: textColor= " @color/white"
android: textStyle= " bold" />
< RadioButton
android: id= " @+id/animation"
android: layout_width= " 0dp"
android: layout_height= " wrap_content"
android: layout_weight= " 1"
android: onClick= " setAnimationFlag"
android: text= " Animation动画"
android: textColor= " @color/white"
android: textStyle= " bold" />
< RadioButton
android: id= " @+id/demoAnimation"
android: layout_width= " 0dp"
android: layout_height= " wrap_content"
android: layout_weight= " 1"
android: onClick= " setAnimationFlag"
android: text= " Demo动画"
android: textColor= " @color/white"
android: textStyle= " bold" />
</ RadioGroup>
</ androidx.appcompat.widget.LinearLayoutCompat>
</ androidx.constraintlayout.widget.ConstraintLayout>
MapMarkAnimate类
常量
public final static String FRAME_ANIMATION = "Frame" ;
public final static String TRANSFORMATION_ANIMATION = "Transformation" ;
public final static String ROTATE_ANIMATION = "Rotate" ;
public final static String ALPHA_ANIMATION = "Alpha" ;
public final static String SCALE_ANIMATION = "Scale" ;
public final static String SINGLE_SCALE_ANIMATION = "SingleScale" ;
public final static String ANIMATION_SET = "AnimationSet" ;
public final static String DEMO_GROW_ANIMATION = "Grow" ;
public final static String DEMO_JUMP_ANIMATION = "Jump" ;
public final static String DEMO_BREATHE_ANIMATION = "Breathe" ;
成员变量
List < BaseOverlay > overlays = new ArrayList < > ( ) ;
List < String > selectedFlags = new ArrayList < > ( ) ;
List < LatLng > points = new ArrayList < > ( ) ;
ArrayList < BitmapDescriptor > bitmaps = new ArrayList < > ( ) ;
BitmapDescriptor circleBitmap;
初始值
selectedFlags. add ( FRAME_ANIMATION ) ;
selectedFlags. add ( FRAME_ANIMATION ) ;
selectedFlags. add ( FRAME_ANIMATION ) ;
points. add ( new LatLng ( 39.97923 , 116.357428 ) ) ;
points. add ( new LatLng ( 39.94923 , 116.397428 ) ) ;
points. add ( new LatLng ( 39.97923 , 116.437428 ) ) ;
points. add ( new LatLng ( 39.92353 , 116.490705 ) ) ;
points. add ( new LatLng ( 40.023537 , 116.289429 ) ) ;
points. add ( new LatLng ( 40.022211 , 116.406137 ) ) ;
int [ ] drawableIds = BubbleIcons. Number ;
for ( int drawableId : drawableIds) {
BitmapDescriptor bitmap = BitmapDescriptorFactory . fromResource ( drawableId) ;
bitmaps. add ( bitmap) ;
}
circleBitmap = BitmapDescriptorFactory . fromResource ( R . drawable. marker_circle_64) ;
创建覆盖物
public void addMarkers ( ) {
if ( selectedFlags. isEmpty ( ) )
return ;
int markerSize = selectedFlags. size ( ) ;
for ( int i = 0 ; i < markerSize; ++ i) {
LatLng point = points. get ( i) ;
String flag = selectedFlags. get ( i) ;
switch ( flag) {
case FRAME_ANIMATION :
addFrameAnimation ( point, bitmaps) ;
break ;
case DEMO_GROW_ANIMATION :
case DEMO_JUMP_ANIMATION :
addSampleAnimation ( point, bitmaps. get ( i) , flag) ;
break ;
case DEMO_BREATHE_ANIMATION :
addBreatheAnimation ( point) ;
break ;
default :
addAnimation ( point, bitmaps. get ( i) , flag) ;
break ;
}
}
}
创建Marker(帧动画)
private void addFrameAnimation ( LatLng point, ArrayList < BitmapDescriptor > bitmaps) {
MarkerOptions option = new MarkerOptions ( )
. position ( point)
. icons ( bitmaps)
. period ( 10 ) ;
Marker marker = map. addMarker ( option) ;
overlays. add ( marker) ;
}
创建Marker(Animation动画)
private void addAnimation ( LatLng point, BitmapDescriptor bitmap, String flag) {
Animation animation = null ;
switch ( flag) {
case TRANSFORMATION_ANIMATION :
animation = getTransformation ( point) ;
break ;
case ROTATE_ANIMATION :
animation = getRotateAnimation ( ) ;
break ;
case ALPHA_ANIMATION :
animation = getAlphaAnimation ( ) ;
break ;
case SCALE_ANIMATION :
animation = getScaleAnimation ( ) ;
break ;
case SINGLE_SCALE_ANIMATION :
animation = getSingleScaleAnimation ( ) ;
break ;
case ANIMATION_SET :
animation = getAnimationSet ( ) ;
break ;
}
if ( animation == null )
return ;
MarkerOptions option = new MarkerOptions ( )
. position ( point)
. icon ( bitmap) ;
Marker marker = map. addMarker ( option) ;
overlays. add ( marker) ;
marker. setAnimation ( animation) ;
marker. startAnimation ( ) ;
}
创建Marker(Demo动画)
private void addSampleAnimation ( LatLng point, BitmapDescriptor bitmap, String flag) {
Animation animation = null ;
switch ( flag) {
case DEMO_GROW_ANIMATION :
animation = getGrowAnimation ( ) ;
break ;
case DEMO_JUMP_ANIMATION :
animation = getJumpAnimation ( point) ;
break ;
}
if ( animation == null )
return ;
MarkerOptions option = new MarkerOptions ( )
. position ( point)
. icon ( bitmap) ;
Marker marker = map. addMarker ( option) ;
overlays. add ( marker) ;
marker. setAnimation ( animation) ;
marker. startAnimation ( ) ;
}
private void addBreatheAnimation ( LatLng point) {
MarkerOptions option = new MarkerOptions ( )
. position ( point)
. icon ( circleBitmap)
. anchor ( 0.5f , 0.5f )
. zIndex ( 1 ) ;
Marker breatheMarker = map. addMarker ( option) ;
overlays. add ( breatheMarker) ;
MarkerOptions centerOption = new MarkerOptions ( )
. position ( point)
. icon ( circleBitmap)
. anchor ( 0.5f , 0.5f )
. zIndex ( 2 ) ;
Marker centerMarker = map. addMarker ( centerOption) ;
overlays. add ( centerMarker) ;
Animation animation = AnimationFactory . getBreatheAnimation ( ) ;
breatheMarker. setAnimation ( animation) ;
breatheMarker. startAnimation ( ) ;
}
创建Animation
创建平移动画、旋转动画、透明度动画、缩放动画、单边缩放动画、创建组合动画、生长动画、跳跃动画、呼吸动画。
Animation getTransformation ( LatLng point) {
Point pt1 = map. getProjection ( ) . toScreenLocation ( point) ;
Point pt2 = new Point ( pt1. x, pt1. y - 100 ) ;
LatLng toPoint = map. getProjection ( ) . fromScreenLocation ( pt2) ;
TranslateAnimation animation = new TranslateAnimation ( toPoint) ;
animation. setDuration ( 500 ) ;
animation. setRepeatMode ( Animation . RESTART ) ;
animation. setRepeatCount ( 1 ) ;
animation. setFillMode ( Animation . FILL_MODE_BACKWARDS ) ;
animation. setAnimationListener ( new Animation. AnimationListener ( ) {
@Override
public void onAnimationStart ( ) {
}
@Override
public void onAnimationEnd ( ) {
}
} ) ;
return animation;
}
Animation getRotateAnimation ( ) {
RotateAnimation animation = new RotateAnimation ( 0f , 360f ) ;
animation. setDuration ( 1000 ) ;
animation. setRepeatMode ( Animation . RESTART ) ;
animation. setRepeatCount ( 1 ) ;
animation. setFillMode ( Animation . FILL_MODE_BACKWARDS ) ;
return animation;
}
Animation getAlphaAnimation ( ) {
float fromAlpha = 1.0f ;
float toAlpha = 0.5f ;
AlphaAnimation animation = new AlphaAnimation ( fromAlpha, toAlpha) ;
animation. setDuration ( 3000 ) ;
animation. setRepeatMode ( Animation . RESTART ) ;
animation. setRepeatCount ( 1 ) ;
animation. setFillMode ( Animation . FILL_MODE_BACKWARDS ) ;
return animation;
}
Animation getScaleAnimation ( ) {
float fromX = 1.0f ;
float toX = 2.0f ;
float fromY = 1.0f ;
float toY = 2.0f ;
ScaleAnimation animation = new ScaleAnimation ( fromX, toX, fromY, toY) ;
animation. setDuration ( 2000 ) ;
animation. setRepeatMode ( Animation . RESTART ) ;
animation. setRepeatCount ( 1 ) ;
animation. setFillMode ( Animation . FILL_MODE_BACKWARDS ) ;
return animation;
}
Animation getSingleScaleAnimation ( ) {
float fromX = 1.0f ;
float toX = 2.0f ;
float fromY = 1.0f ;
float toY = 1.0f ;
ScaleAnimation animation = new ScaleAnimation ( fromX, toX, fromY, toY) ;
animation. setDuration ( 1000 ) ;
animation. setRepeatMode ( Animation . RESTART ) ;
animation. setRepeatCount ( 1 ) ;
animation. setFillMode ( Animation . FILL_MODE_BACKWARDS ) ;
return animation;
}
Animation getAnimationSet ( ) {
boolean shareInterpolator = true ;
AnimationSet animation = new AnimationSet ( shareInterpolator) ;
animation. addAnimation ( getAlphaAnimation ( ) ) ;
animation. addAnimation ( getRotateAnimation ( ) ) ;
animation. addAnimation ( getScaleAnimation ( ) ) ;
animation. setInterpolator ( new LinearInterpolator ( ) ) ;
return animation;
}
Animation getGrowAnimation ( ) {
float fromX = 0.0f ;
float toX = 1.0f ;
float fromY = 0.0f ;
float toY = 1.0f ;
ScaleAnimation animation = new ScaleAnimation ( fromX, toX, fromY, toY) ;
animation. setInterpolator ( new LinearInterpolator ( ) ) ;
animation. setDuration ( 1000 ) ;
return animation;
}
Animation getJumpAnimation ( LatLng point) {
Point pt1 = map. getProjection ( ) . toScreenLocation ( point) ;
Point pt2 = new Point ( pt1. x, pt1. y - 100 ) ;
LatLng toPoint = map. getProjection ( ) . fromScreenLocation ( pt2) ;
Animation animation = new TranslateAnimation ( toPoint) ;
animation. setInterpolator ( new Interpolator ( ) {
@Override
public float getInterpolation ( float input) {
if ( input <= 0.5 ) {
return ( float ) ( 0.5f - 2 * ( 0.5 - input) * ( 0.5 - input) ) ;
} else {
return ( float ) ( 0.5f - Math . sqrt ( ( input - 0.5f ) * ( 1.5f - input) ) ) ;
}
}
} ) ;
animation. setDuration ( 600 ) ;
return animation;
}
Animation getBreatheAnimation ( ) {
boolean shareInterpolator = true ;
AnimationSet animationSet = new AnimationSet ( shareInterpolator) ;
float fromAlpha = 0.5f ;
float toAlpha = 0f ;
AlphaAnimation alphaAnimation = new AlphaAnimation ( fromAlpha, toAlpha) ;
alphaAnimation. setDuration ( 2000 ) ;
alphaAnimation. setRepeatCount ( Animation . INFINITE ) ;
float fromX = 1.0f ;
float toX = 3.5f ;
float fromY = 1.0f ;
float toY = 3.5f ;
ScaleAnimation scaleAnimation = new ScaleAnimation ( fromX, toX, fromY, toY) ;
scaleAnimation. setDuration ( 2000 ) ;
scaleAnimation. setRepeatCount ( Animation . INFINITE ) ;
animationSet. addAnimation ( alphaAnimation) ;
animationSet. addAnimation ( scaleAnimation) ;
animationSet. setInterpolator ( new LinearInterpolator ( ) ) ;
return animationSet;
}
移除覆盖物
public void removeOverlay ( ) {
for ( BaseOverlay overlay : overlays) {
if ( overlay instanceof Marker ) {
Marker marker = ( Marker ) overlay;
marker. remove ( ) ;
}
}
overlays. clear ( ) ;
}
设置属性
public void setFlags ( List < String > flags) {
selectedFlags. clear ( ) ;
selectedFlags. addAll ( flags) ;
removeOverlay ( ) ;
addMarkers ( ) ;
}
加载地图和释放地图
public void onMapLoaded ( ) {
addMarkers ( ) ;
}
public void onMapDestroy ( ) {
removeOverlay ( ) ;
for ( BitmapDescriptor bitmap : bitmaps) {
bitmap. recycle ( ) ;
}
bitmaps = null ;
if ( circleBitmap != null )
circleBitmap. recycle ( ) ;
circleBitmap = null ;
}
MapMarkerAnimationActivity类
以下是MapMarkerAnimationActivity
类部分代码
控件响应事件
public void setAnimationFlag ( View view) {
boolean checked = ( ( RadioButton ) view) . isChecked ( ) ;
int id = view. getId ( ) ;
if ( ! checked)
return ;
List < String > flags;
if ( id == R . id. frameAnimation) {
flags = Arrays . asList (
MapMarkerAnimation . FRAME_ANIMATION ,
MapMarkerAnimation . FRAME_ANIMATION ,
MapMarkerAnimation . FRAME_ANIMATION ) ;
} else if ( id == R . id. animation) {
flags = Arrays . asList (
MapMarkerAnimation . TRANSFORMATION_ANIMATION ,
MapMarkerAnimation . ROTATE_ANIMATION ,
MapMarkerAnimation . ALPHA_ANIMATION ,
MapMarkerAnimation . SCALE_ANIMATION ,
MapMarkerAnimation . SINGLE_SCALE_ANIMATION ,
MapMarkerAnimation . ANIMATION_SET ) ;
} else if ( id == R . id. demoAnimation) {
flags = Arrays . asList (
MapMarkerAnimation . DEMO_GROW_ANIMATION ,
MapMarkerAnimation . DEMO_JUMP_ANIMATION ,
MapMarkerAnimation . DEMO_BREATHE_ANIMATION ) ;
} else {
return ;
}
mapMarkerAnimation. setFlags ( flags) ;
}
运行效果图