项目中需要在百度地图上完成一个从一个图片底部慢慢上升的动画效果,
先讲一下原来的思路,因为安卓有一个动画效果是可以从底部上升的,当时就想着只要实现动画效果,放在地图上就是了,后来发现百度地图好像不支持这种动画,自己提供的动画是需要一组图片组合的,总不能设置100个图片吧。所以换了思路。先介绍当时参考的两篇文章。
第一篇是关于动画的,动画效果,ClipDrawable是裁剪动画,Android中的进度条就是使用ClipDrawable来实现的,根据设置level的值来决定剪切区域的大小。现在先介绍一下用法
相关属性:
clipOrietntion:设置剪切的方向,可以设置水平和竖直2个方向
gravity:从那个位置开始裁剪
drawable:引用的drawable资源,为空的话需要有一个Drawable类型的子节点
使用示例:
核心就是通过代码修改ClipDrawable的level即可!
这里我们实现一个类似于进度条的效果,另外这个Level的值是0~10000哦:
①定义一个ClipDrawable的资源xml:
<?xml version="1.0" encoding="utf-8"?> <clip xmlns:android="http://schemas.android.com/apk/res/android" android:clipOrientation="horizontal" android:drawable="@drawable/load" android:gravity="left" />
②在activity_main主布局文件中设置一个ImageView,将src设置为clipDrawable!,写成了blackground的话可是会报空指针
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context="com.jay.example.drawabletest.MainActivity" > <ImageView android:id="@+id/imgShow1" android:layout_width="match_parent" android:layout_height="match_parent" android:src="@drawable/clip_one" /> </LinearLayout>
代码中调用
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 0x123) {
cd.setLevel(cd.getLevel() + 500);
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imgShow1 = (ImageView) findViewById(R.id.imgShow1);
// 核心实现代码
cd = (ClipDrawable) imgShow1.getDrawable();
final Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
handler.sendEmptyMessage(0x123);
if (cd.getLevel() >= 10000) {
timer.cancel();
}
}
}, 0, 300);
}
第二篇是关于地图自定义动画的地图自定义动画
先说一下本例实现的思路吧,先传两张照片,对比一下,
说明一下,第一张图片是默认的进度为0,第二张图片是进度为100的,思路就是以进度为0的图片作为背景,也就是在某一坐标点上进行标注,第二张图片在同一坐标点上进行标注,第一张图片不动,第二张图片也就是进度100的图片,则进行裁剪,每隔一段时间只显示一部分,举个例子,10秒的时候进度是10,则只显示图片十分之一的高度,然后20秒显示五分之一的高度,用五分之一高度的图片替换十分之一高度的图片,并且将十分之一高度的图片释放掉。简单说吧,就是进度为0的图片不动,进度为100的图片根据时间只显示一部分。
在上代码之前,先说一下做百度地图需要注意的地方,也是纠结了我好长时间的地方,百度地图提供了不少demo,然后每一个跑起来都是可以的,问题就是组合起来会出不少问题,我的经验就是1.尽量不要用demo里边的.jar或者.so文件,要在这个地方下载百度地图SDK下载,2.最好先写一个小demo,把需要组合的功能调试成功再放到自己的项目里边,3.要对自己的项目勤备份,尤其是有大的改动之前,万一开发中出现什么问题,还可以找到原来的备份进行修改
好了,先上代码吧
1.进度为0的图片在地图上设置标注
将进度为0的图片放在地图上进行标注,作为背景,xml布局中只有一个地图,就不写了
//获取地图控件引用
mMapView = (MapView) view.findViewById(R.id.bmapView);
mBaiduMap = mMapView.getMap();
//定义Maker坐标点
pt = new LatLng(31.546372, 120.297545);
Bitmap bitmapBack = BitmapFactory.decodeResource(getActivity().getResources(), R.mipmap.charge_0);
BitmapDescriptor bitmapDescriptorBack = BitmapDescriptorFactory.fromBitmap(bitmapBack);
//构建MarkerOption,用于在地图上添加Marker
OverlayOptions option = new MarkerOptions()
.position(pt)
.icon(bitmapDescriptorBack);
mBaiduMap.addOverlay(option);
2.进度为100的图片随时间显示高度递增
先来说一下裁剪方法
public static Bitmap createBitmap (Bitmap source, int x, int y, int width, int height, Matrix m, boolean filter)
属性说明:
surce:用来剪裁的图片源;
x:剪裁x方向的起始位置;
y:剪裁y方向的起始位置;
width:剪裁的宽度;
height:剪裁的高度;
filer:???
思路就是定义一个handler,然后随时间进行裁剪图片高度,裁剪不同的图片,用新图片在进度为0图片标注的坐标点进行标注,释放掉旧图片,点击按钮开启handler,
代码
private PopupWindow popupWindow;
private Bitmap bitmapCharging = null;//图片
private Bitmap bitmapChargingCrop = null;//裁剪以后的图片
private Marker mMarkCharging = null;//图片在地图上显示的mark
private Marker oldMark;
private BitmapDescriptor bitmapDescriptor;
private Button buttonProgress;
//进度值
private int chargingProgress = 0;
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 0x123) {
chargingProgress++;
if (bitmapCharging != null) {
int bitHeight = bitmapCharging.getHeight();
int bitmapProgress = chargingProgress * bitHeight / 100;//实际图片需要截取的高度,进度是0~100,换算
if (bitmapChargingCrop != null) {
bitmapChargingCrop.recycle();//释放掉之前的裁剪的图片
}
if (bitmapDescriptor != null) {
bitmapDescriptor.recycle();//释放掉之前的裁剪的图片
}
if (bitHeight - bitmapProgress >= 0) {
if (chargingProgress > 100) {
chargingProgress = 100;
}
buttonProgress.setText((chargingProgress) + "%");
int height = bitmapCharging.getHeight();
int a = bitHeight - bitmapProgress;
L.e("height", height + "," + a);
try {
bitmapChargingCrop = Bitmap.createBitmap(bitmapCharging, 0, bitHeight - bitmapProgress, bitmapCharging.getWidth(), bitmapProgress);//裁剪以后的图片
bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(bitmapChargingCrop);
OverlayOptions option = new MarkerOptions()
.position(pt)
.icon(bitmapDescriptor);
oldMark = mMarkCharging;
if (oldMark != null) {
oldMark.remove();
}
mMarkCharging = (Marker) (mBaiduMap.addOverlay(option));
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
};
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
bitmapCharging = BitmapFactory.decodeResource(getActivity().getResources(), R.mipmap.charge_100);
Button buttonAdd = (Button) view.findViewById(R.id.id_addY);
buttonAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final Timer timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
handler.sendEmptyMessage(0x123);
if (chargingProgress >= 100) {
timer.cancel();
}
}
}, 0, 300);
}
});
}
3.显示进度文字
这个我就偷懒了,百度地图上不是有一个InfoWindow吗,而且自定义的还需要图片背景,我就是用了一个透明图片,然后在上边写字,还有一个就是为了显示清楚,需要设置字体阴影,使用这个方法
public void setShadowLayer (float radius, float dx, float dy, int color)
radius:阴影半径
dx:X轴方向的偏移量
dy:Y轴方向的偏移量
color:阴影颜色
ok,上代码
//创建InfoWindow展示的view
buttonProgress = new Button(getActivity());
buttonProgress.setTextSize(13);
//阴影效果, public void setShadowLayer (float radius, float dx, float dy, int color)
//radius:阴影半径
// dx:X轴方向的偏移量
// dy:Y轴方向的偏移量
// color:阴影颜色
// 注意:如果半径被设置为0,意思就是去掉阴影。
buttonProgress.setShadowLayer(1F, 1F, 5F, Color.BLACK);
TextPaint tp = buttonProgress.getPaint();
tp.setFakeBoldText(true);
buttonProgress.setTextColor(getActivity().getResources().getColor(R.color.text_progress));
buttonProgress.setBackgroundResource(R.drawable.alpha);
InfoWindow mInfoWindow = new InfoWindow(buttonProgress, pt, -bitmapBack.getWidth() / 4);
//显示InfoWindow
mBaiduMap.showInfoWindow(mInfoWindow);
项目比较近,所以我只想到这样的实现方法,应该还会有更好的方法的。。。