高德地图SDK Android版开发 8 覆盖物示例2动画 前言 动画相关的类和接口 帧动画 Animation动画 Animation类及其子类 Animation TranslateAnimation RotateAnimation AlphaAnimation ScaleAnimation AnimationSet Marker动画示例 界面布局 MapMarkAnimate类 常量 成员变量 初始值 创建覆盖物 创建Marker(帧动画) 创建Marker(Animation动画) 创建Marker(Demo动画) 创建Animation 移除覆盖物 设置属性 加载地图和释放地图 MapMarkerAnimationActivity类 运行效果图
前言
前文介绍了高德地图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.MapViewandroid: 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.LinearLayoutCompatandroid: 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" > < RadioGroupandroid: 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" > < RadioButtonandroid: 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" /> < RadioButtonandroid: 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" /> < RadioButtonandroid: 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) ;
}
运行效果图