Android百度地图轨迹播放暂停速度调控,进度调控
摘要:之前看到了百度地图的api以为Android的实现方式也是很简单的,结果百度地图的demo并没有Android的轨迹播放的demo,有的也是简单的轨迹播放并没有进度和速度的控制,最后只能是自己做的。
可以是实现小汽车轨迹的平滑移动,并且并且弹框的内容可以跟着小汽车的变化而变化。汽车轨迹播放的暂停与播放,进度的控制,速度的控制,并且如果车辆是移动到外面的还可以自动移动到屏幕中间
一:结果展示(因为gif的大小只能是5M所以录制的比较少 )
二:代码展示
activity的代码展示
这里请求的是本地的json格式的数据,但是里面也注释了HTTP的请求方式有需要的可以参考。
package com.boxin.truck.activity.manager;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.graphics.Point;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import com.baidu.mapapi.map.BaiduMap;
import com.baidu.mapapi.map.BitmapDescriptor;
import com.baidu.mapapi.map.BitmapDescriptorFactory;
import com.baidu.mapapi.map.InfoWindow;
import com.baidu.mapapi.map.MapStatus;
import com.baidu.mapapi.map.MapStatusUpdate;
import com.baidu.mapapi.map.MapStatusUpdateFactory;
import com.baidu.mapapi.map.MapView;
import com.baidu.mapapi.map.Marker;
import com.baidu.mapapi.map.MarkerOptions;
import com.baidu.mapapi.map.OverlayOptions;
import com.baidu.mapapi.map.Polyline;
import com.baidu.mapapi.map.PolylineOptions;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.model.LatLngBounds;
import com.boxin.truck.R;
import com.boxin.truck.map.MapActivity;
import com.boxin.truck.model.BaiduTrack;
import com.boxin.truck.util.JsonUtils;
import com.boxin.truck.util.LogUtils;
import com.boxin.truck.util.TimeUtils;
import com.boxin.truck.util.ToastUtils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
/**
* Created by lsx on 2020/03/17.
* 轨迹播放
*/
public class BaiduTrackActivity extends MapActivity implements View.OnClickListener {
@BindView(R.id.title_tv)
public TextView mTitleTV;
@BindView(R.id.back_container)
public RelativeLayout mBackContainer;
@BindView(R.id.linearLayout)
public LinearLayout linearLayout;
@BindView(R.id.bmapView)
protected MapView bmapView;
@BindView(R.id.map)
protected com.google.android.gms.maps.MapView googleView;
@BindView(R.id.data_container)
public LinearLayout mDataContainer;
@BindView(R.id.top_truck_container)
public RelativeLayout mTopTruckContainer;
@BindView(R.id.top_truck_tv)
public TextView mTopTruckTV;
@BindView(R.id.loading_container)
public RelativeLayout loadingContainer;
@BindView(R.id.txt_bmap_top_name)
public TextView txtName;
@BindView(R.id.txt_bmap_top_speed)
public TextView txtSpeed;
@BindView(R.id.txt_bmap_top_time)
public TextView txtTime;
@BindView(R.id.play_btn)
public ImageView mPlayBtn;
@BindView(R.id.progress_bar)
public SeekBar mProgressBar;
@BindView(R.id.speed_bar)
public SeekBar mSpeedBar;
private static final String TAG = "GoogleTraceActivity";
public static final String BUNDLE_PLATENUMBER = "mPlateNumber";
public static final String BUNDLE_DATA_MILEAGE_DAILY = "mileageDaily";
protected BaiduMap mMap;
private BitmapDescriptor startBmp, endBmp, currentBmp;
private BitmapDescriptor mGreenTexture = BitmapDescriptorFactory.fromAsset("Icon_road_green_arrow.png");
private Polyline mPolyline;
private Marker mMoveMarker;
private Handler mHandler;
private List<LatLng> polyLineList;
public ArrayList<BaiduTrack> routePoints = new ArrayList<>();
volatile boolean isMoving = true; //是否开始运动
volatile boolean AnimationEnd = false; //动画是否播放结束
private LatLng mLastLatLng = null; //保存移动到具体的某个点
private double slope; //调整的坡
private boolean isYReverse; //调整后的Y轴
private boolean isXReverse;//调整后的X轴
private double intercept;// 根据点和斜率算取截距
private double xMoveDistance; //X轴移动的距离
private double yMoveDistance; //Y轴移动的距离
private LatLng lastStartPoint;//保存上一个起点
private LinearLayout mInfoWindowLayout;//提示框
private TextView mSpeed,mSpeedTV, mTimeTv; //文字信息
private boolean isFirstStartThread = true;
// 通过设置间隔时间和距离可以控制速度和图标移动的距离
private int mNotChangeTime = 100;//默认1000毫秒
volatile int mSleepTime = 100;
volatile double mDistance = 0.00002;
boolean state = true;//点击播放为true,点击暂停为false
private LayoutInflater factory;//引入新的弹框样式
private View layout;//初始化弹框样式
@SuppressLint("baiDuHandler")
private Handler myHandler = new Handler() {
public void handleMessage(Message msg) {
Bundle bundle = msg.getData();
//类型为1的是实时监控marker的数据改变,类型为2是车辆运动到最后弹出警示和设置暂停按钮
if (bundle.getString("type").equals("1")) {
mSpeedTV.setText(bundle.getString("speed"));
mTimeTv.setText(bundle.getString("time"));
mMoveMarker.getInfoWindow().setBitmapDescriptor(BitmapDescriptorFactory.fromView(layout));
} else if (bundle.getString("type").equals("2")) {
showLimitTips();
mPlayBtn.setBackground(getResources().getDrawable(R.drawable.map_icon_stop));
}
super.handleMessage(msg);
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_map_track);
ButterKnife.bind(this);
ButterKnife.bind(this);
getPermission();
initView();
loadData();
}
/**
* 方法必须重写
*/
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
bmapView.onSaveInstanceState(outState);
}
public void initView() {
//mileageDailySubclass= (MileageDailySubclass) getIntent().getExtras().getSerializable(BUNDLE_DATA_MILEAGE_DAILY);
// mTitleTV.setText(mileageDailySubclass.getPlateNumber());
mTitleTV.setText("轨迹回放");
mBackContainer.setVisibility(View.VISIBLE);
polyLineList = new ArrayList<>();
mTopTruckContainer.setVisibility(View.VISIBLE);
googleView.setVisibility(View.GONE);
bmapView.setVisibility(View.VISIBLE);
mDataContainer.setVisibility(View.VISIBLE);
loadingContainer.setVisibility(View.VISIBLE);
mMap = bmapView.getMap();
mMap.getUiSettings().setRotateGesturesEnabled(false);//不允许旋转地图
mMap.getUiSettings().setZoomGesturesEnabled(true);
mMap.getUiSettings().setCompassEnabled(true);
mMap.setTrafficEnabled(false);
mMap.setBuildingsEnabled(false);
mMap.setIndoorEnable(false);
mMap.getUiSettings().setAllGesturesEnabled(true);
startBmp = BitmapDescriptorFactory.fromResource(R.drawable.icon_map_start_point);
endBmp = BitmapDescriptorFactory.fromResource(R.drawable.destination);
currentBmp = BitmapDescriptorFactory.fromResource(R.drawable.ic_truck);
//初始化弹框样式
factory= LayoutInflater.from(BaiduTrackActivity.this) ;
layout=factory.inflate(R.layout.map_bullet_box, null);
mSpeedTV = (TextView) layout.findViewById(R.id.speed_tv);
mTimeTv = (TextView) layout.findViewById(R.id.time_tv);
//顶部样式隐藏与显示
mTopTruckContainer.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (mDataContainer.getVisibility() == View.GONE) {
mDataContainer.setVisibility(View.VISIBLE);
mTopTruckTV.setText("隐藏");
} else {
mDataContainer.setVisibility(View.GONE);
mTopTruckTV.setText("显示");
}
}
});
//进度监听
mProgressBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean b) {
//Log.e("size",progress+"--");
if (routePoints == null || routePoints.size() == 0) {
return;
}
if (progress == routePoints.size() - 1) {
//设置按钮
mPlayBtn.setBackgroundResource(R.drawable.map_icon_stop);
isMoving = false;
//设置终点marker
if (mMoveMarker != null) {
mMoveMarker.setIcon(BitmapDescriptorFactory.fromResource(R.drawable.ic_truck));
}
}
if (progress < routePoints.size() - 1)
ai.set(progress);
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
LogUtils.i(TAG, "点击了进度条");
isMoving = false;
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
LogUtils.i(TAG, "停止点击进度条");
if (!state)
isMoving = true;
}
});
//速度监听
mSpeedBar.setMax(mNotChangeTime);
mSpeedBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
if (routePoints == null || routePoints.size() == 0) {
return;
}
if (mSleepTime > 0) {
mSleepTime = mNotChangeTime - i;
mDistance = i * 0.000005 + 0.00002;
}
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
LogUtils.i(TAG, "点击了速度进度条");
isMoving = false;
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
LogUtils.i(TAG, "停止点击速度进度条");
if (!state)
isMoving = true;
}
});
mHandler = new Handler(Looper.getMainLooper());
}
public void loadData() {
/* HashMap<String, String> params = new HashMap<>();
params.put("boxId", mileageDailySubclass.getBoxId());
params.put("beginDate",TimeUtils.f_long_2_str(mileageDailySubclass.getStartTime().getTime()));
params.put("endDate",TimeUtils.f_long_2_str(mileageDailySubclass.getEndTime().getTime()));
params.put("mapType","1");
LogUtils.i(TAG, "queryTrajectoryUrl=" + UrlConfig.getTrajectory() + " ,params=" + params);
HttpProxy.getInstance().post(this, UrlConfig.getTrajectory(), params, new ICallback() {
@Override
public void onFailure(String e) {
LogUtils.i(TAG,"MileageDailyDetail-err"+e);
}
@Override
public void onResponse(String result) {
LogUtils.i(TAG, "MileageDailyDetail-result=" + result);
ArrayList<BaiduTrack> tracks = (ArrayList<BaiduTrack>) JsonUtils.MultipleJson(result, BaiduTrack.class);
for(int j=0;j<tracks.size();j++){
polyLineList.add(new LatLng(tracks.get(j).getLatitude(),tracks.get(j).getLongitude()));
}
routePoints=tracks;
drawPolyLine();
TrackThread trackThread = new TrackThread(routePoints,mMoveMarker,mMap,mHandler,mPolyline);
trackThread.start();
loadingContainer.setVisibility(View.GONE);
}
});*/
String result = getData();
if (result != null) {
routePoints = (ArrayList<BaiduTrack>) JsonUtils.MultipleJson(result, BaiduTrack.class);
for (int j = 0; j < routePoints.size(); j++) {
polyLineList.add(new LatLng(routePoints.get(j).getLatitude(), routePoints.get(j).getLongitude()));
}
drawPolyLine();
loadingContainer.setVisibility(View.GONE);
}
}
@OnClick({R.id.back_container, R.id.play_btn})
@Override
public void onClick(View v) {
int id = v.getId();
switch (id) {
case R.id.back_container:
finish();
isMoving = false;
break;
case R.id.play_btn:
if (ai.get() != routePoints.size() - 1) {
if (state) {
isMoving = true;
state = false;
mPlayBtn.setBackground(getResources().getDrawable(R.drawable.map_icon_broadcast));
if (isFirstStartThread) {
moveLooper();
isFirstStartThread = false;
if (null != polyLineList) {
MapStatus mapStatus = new MapStatus.Builder().target(polyLineList.get(0)).zoom(18).build();
mMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus(mapStatus));
}
}
} else {
isMoving = false;
state = true;
mPlayBtn.setBackground(getResources().getDrawable(R.drawable.map_icon_stop));
}
} else {
showLimitTips();
}
}
}
@Override
protected void onResume() {
super.onResume();
bmapView.onResume();
}
@Override
protected void onPause() {
super.onPause();
bmapView.onPause();
}
@Override //再次进入该activity重新创建activity,从而到达数据刷新的效果
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}
@Override
public void onDestroy() {
super.onDestroy();
mMap.clear();
bmapView.onDestroy();
}
@Override
protected void onStop() {
super.onStop();
}
/**
* 绘画轨迹线
*/
private void drawPolyLine() {
// 绘制纹理PolyLine
PolylineOptions polylineOptions = new PolylineOptions().points(polyLineList).width(10).customTexture(mGreenTexture)
.dottedLine(true);
mPolyline = (Polyline) mMap.addOverlay(polylineOptions);
final int count = polyLineList.size() - 1;
// progressBar.setMax(count);
mProgressBar.setMax(count);
//第一次进入地图,将整条的路线在可见的屏幕上。
LatLngBounds.Builder builder = new LatLngBounds.Builder();
for (LatLng p : polyLineList) {
builder.include(p);
}
MapStatusUpdate msUpdate = MapStatusUpdateFactory.newLatLngBounds(builder.build());
mMap.animateMapStatus(msUpdate);
// 添加小车marker
OverlayOptions markerOptions = new MarkerOptions().flat(true).anchor(0.5f, 0.5f).icon(currentBmp).
position(polyLineList.get(0)).rotate((float) getAngle(0));
mMoveMarker = (Marker) mMap.addOverlay(markerOptions);
//添加起点的定位icon
OverlayOptions startOptions = new MarkerOptions().icon(startBmp).position(polyLineList.get(0));
mMap.addOverlay(startOptions);
//添加终点的定位icon
OverlayOptions endOptions = new MarkerOptions().icon(endBmp).position(polyLineList.get(polyLineList.size() - 1));
mMap.addOverlay(endOptions);
InfoWindow.OnInfoWindowClickListener infoWindowClickListener = new InfoWindow.OnInfoWindowClickListener() {
@Override
public void onInfoWindowClick() {
// Toast.makeText(BaiduTrackActivity.this, "点击了InfoWindow", Toast.LENGTH_SHORT).show();
}
};
mSpeedTV.setText(String.format("%.2f", routePoints.get(0).getSpeed()) + "km/h");
mTimeTv.setText(TimeUtils.f_long_2_str(routePoints.get(0).getLoc_time() * 1000));
// 添加 Marker 关联的InfoWindow,两者的更新是相互独立的。
mMoveMarker.showInfoWindow(new InfoWindow(BitmapDescriptorFactory.fromView(layout), polyLineList.get(0), -47,
infoWindowClickListener));
}
/**
* 循环进行移动逻辑
*/
AtomicInteger ai = new AtomicInteger(0);
public void moveLooper() {
new Thread() {
public void run() {
while (true) {
for (int i = 0; i < routePoints.size() - 2; ) {
if (isMoving) {
i = ai.get();
//获取两个点,判断车辆移动的方向
LatLng startPoint = new LatLng(routePoints.get(i).getLatitude(), routePoints.get(i).getLongitude());
LatLng endPoint = new LatLng(routePoints.get(i + 1).getLatitude(), routePoints.get(i + 1).getLongitude());
if (null != mLastLatLng && null != lastStartPoint) {
//判断一个点的起始点是否和上一个点的起始点是一样的。如果是一样的话就不进行角度的偏移。
if (startPoint.latitude == lastStartPoint.latitude && startPoint.longitude == lastStartPoint.longitude) {
moveMarker(mLastLatLng, endPoint, false, routePoints.get(i));
} else {
moveMarker(startPoint, endPoint, true, routePoints.get(i));
}
} else
moveMarker(startPoint, endPoint, true, routePoints.get(i));
//保存上运动点的起始经纬度
lastStartPoint = new LatLng(startPoint.latitude, startPoint.longitude);
ai.addAndGet(1);
if (i == routePoints.size() - 2) {
isMoving = false;
state = true;
Message message = new Message();
Bundle bundle = new Bundle();
bundle.putString("type", "2");
message.setData(bundle);
myHandler.sendMessage(message);
AnimationEnd = true;
}
}
}
}
}
}.start();
}
/**
* 小车的移动
*/
public void moveMarker(LatLng startPoint, LatLng endPoint, boolean right, BaiduTrack baiduTracks) {
if (isMoving) {
if (right) {
mMoveMarker.setPosition(startPoint);
mHandler.post(new Runnable() {
@Override
public void run() {
// refresh marker's rotate
if (mMap == null) {
return;
}
//marker根据角度旋转车的角度
mMoveMarker.setRotate((float) getAngle(startPoint, endPoint));
}
});
slope = getSlope(startPoint, endPoint);
// 是不是正向的标示
isYReverse = (startPoint.latitude > endPoint.latitude);
isXReverse = (startPoint.longitude > endPoint.longitude);
intercept = getInterception(slope, startPoint);
xMoveDistance = isXReverse ? getXMoveDistance(slope) : -1 * getXMoveDistance(slope);
yMoveDistance = isYReverse ? getYMoveDistance(slope) : -1 * getYMoveDistance(slope);
Message message = new Message();
Bundle bundle = new Bundle();
bundle.putString("type", "1");
bundle.putString("speed", String.format("%.2f", baiduTracks.getSpeed()) + "km/h");
bundle.putString("time", TimeUtils.f_long_2_str(baiduTracks.getLoc_time() * 1000));
message.setData(bundle);
myHandler.sendMessage(message);
//设置进度条的位置
mProgressBar.setProgress(ai.get());
}
//无限分割上传的两个点并且循环移动这两个点之间的所有点。
for (double j = startPoint.latitude, k = startPoint.longitude;
!((j > endPoint.latitude) ^ isYReverse) && !((k > endPoint.longitude) ^ isXReverse); ) {
if (!isMoving) {
//如果是没有移动状态的话,那么这两个点的起始点需要回滚到前一个点中,并且跳出该两点的循环。
ai.addAndGet(-1);
break;
}
LatLng latLng = null;
if (slope == Double.MAX_VALUE) {
latLng = new LatLng(j, k);
j = j - yMoveDistance;
} else if (slope == 0.0) {
latLng = new LatLng(j, k - xMoveDistance);
k = k - xMoveDistance;
} else {
latLng = new LatLng(j, (j - intercept) / slope);
j = j - yMoveDistance;
}
final LatLng finalLatLng = latLng;
mLastLatLng = latLng;
if (finalLatLng.latitude == 0 && finalLatLng.longitude == 0) {
continue;
}
mHandler.post(new Runnable() {
@Override
public void run() {
if (mMap == null) {
return;
}
mMoveMarker.setPosition(finalLatLng);
// 设置 Marker 覆盖物的位置坐标,并同步更新与Marker关联的InfoWindow的位置坐标.
mMoveMarker.setPositionWithInfoWindow(finalLatLng);
//设置marker的位置不移动出屏幕
if (finalLatLng != null) {
Point pt = mMap.getMapStatus().targetScreen;
Point point = mMap.getProjection().toScreenLocation(finalLatLng);
if (point.x < 0 || point.x > pt.x * 2 || point.y < 0 || point.y > pt.y * 2) {
mMap.animateMapStatus(MapStatusUpdateFactory.newLatLng(finalLatLng));
}
}
}
});
try {
Thread.sleep(mSleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
/**
* 根据数字返回方向
*
* @param d
* @return
*/
private String directionType(int d) {
if ((d >= 337 && d <= 360) || (d >= 0 && d <= 23)) {
return "北向";
} else if (d >= 23 && d <= 68) {
return "东北向";
} else if (d >= 68 && d <= 113) {
return "东向";
} else if (d >= 113 && d <= 158) {
return "东南向";
} else if (d >= 158 && d <= 203) {
return "南向";
} else if (d >= 203 && d <= 248) {
return "西南向";
} else if (d >= 248 && d <= 293) {
return "西向";
} else //if (d >= 293 && d <= 338) {
return "西北向";
}
/**
* 计算x方向每次移动的距离
*/
private double getXMoveDistance(double slope) {
if (slope == Double.MAX_VALUE || slope == 0.0) {
return mDistance;
}
return Math.abs((mDistance * 1 / slope) / Math.sqrt(1 + 1 / (slope * slope)));
}
/**
* 计算y方向每次移动的距离
*/
private double getYMoveDistance(double slope) {
if (slope == Double.MAX_VALUE || slope == 0.0) {
return mDistance;
}
return Math.abs((mDistance * slope) / Math.sqrt(1 + slope * slope));
}
/**
* 算斜率
*/
private double getSlope(LatLng fromPoint, LatLng toPoint) {
if (toPoint.longitude == fromPoint.longitude) {
return Double.MAX_VALUE;
}
double slope = ((toPoint.latitude - fromPoint.latitude) / (toPoint.longitude - fromPoint.longitude));
return slope;
}
/**
* 根据点和斜率算取截距
*/
private double getInterception(double slope, LatLng point) {
double interception = point.latitude - slope * point.longitude;
return interception;
}
/**
* 根据点获取图标转的角度
*/
private double getAngle(int startIndex) {
if ((startIndex + 1) >= mPolyline.getPoints().size()) {
throw new RuntimeException("index out of bonds");
}
LatLng startPoint = mPolyline.getPoints().get(startIndex);
LatLng endPoint = mPolyline.getPoints().get(startIndex + 1);
return getAngle(startPoint, endPoint);
}
/**
* 根据两点算取图标转的角度
*/
private double getAngle(LatLng fromPoint, LatLng toPoint) {
double slope = getSlope(fromPoint, toPoint);
if (slope == Double.MAX_VALUE) {
if (toPoint.latitude > fromPoint.latitude) {
return 0;
} else {
return 180;
}
} else if (slope == 0.0) {
if (toPoint.longitude > fromPoint.longitude) {
return -90;
} else {
return 90;
}
}
float deltAngle = 0;
if ((toPoint.latitude - fromPoint.latitude) * slope < 0) {
deltAngle = 180;
}
double radio = Math.atan(slope);
double angle = 180 * (radio / Math.PI) + deltAngle - 90;
return angle;
}
private void showLimitTips() {
ToastUtils.getInstance().shortShow(this, getString(R.string.track_playback_end));
}
private String getData() {
StringBuilder newstringBuilder = new StringBuilder();
InputStream inputStream = null;
try {
inputStream = getResources().getAssets().open("baiduTrack.json");
InputStreamReader isr = new InputStreamReader(inputStream);
BufferedReader reader = new BufferedReader(isr);
String jsonLine;
while ((jsonLine = reader.readLine()) != null) {
newstringBuilder.append(jsonLine);
}
reader.close();
isr.close();
inputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
String result = newstringBuilder.toString();
Log.d("json", result);
return result;
}
}
xml文件 activity_map_track.xml文件
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/linearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--标题-->
<include
android:id="@+id/title_container"
layout="@layout/top_titile_view" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_below="@+id/data_container"
android:background="#80000000"
android:visibility="gone">
<TextView
android:id="@+id/txt_bmap_top_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/white"/>
<TextView
android:id="@+id/txt_bmap_top_speed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/white"/>
<TextView
android:id="@+id/txt_bmap_top_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@android:color/white"/>
</LinearLayout>
<!--百度地图-->
<com.baidu.mapapi.map.MapView
android:id="@+id/bmapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/bottom_layout"
android:layout_below="@+id/data_container"
android:visibility="gone"
/>
<!--谷歌地图-->
<!--底部按钮控制开始动画-->
<com.google.android.gms.maps.MapView
android:id="@+id/map"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/bottom_layout"
android:layout_below="@+id/data_container" />
<!--进度控制-->
<RelativeLayout
android:id="@+id/bottom_layout"
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_alignParentBottom="true"
android:background="@color/white"
>
<ImageView
android:id="@+id/play_btn"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerVertical="true"
android:layout_marginLeft="15dp"
android:background="@drawable/map_icon_stop"
android:scaleType="fitXY" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerVertical="true"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_toRightOf="@+id/play_btn"
android:gravity="center_vertical"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="进度"
android:textColor="#333333"
android:textSize="14sp" />
<SeekBar
android:id="@+id/progress_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxHeight="3dp"
android:minHeight="3dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:progressDrawable="@drawable/map_bg_adjust_seek_bar"
android:thumb="@drawable/map_icon_destination" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="速度"
android:textColor="#333333"
android:textSize="14sp" />
<SeekBar
android:id="@+id/speed_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxHeight="3dp"
android:minHeight="3dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:progressDrawable="@drawable/map_bg_adjust_seek_bar"
android:thumb="@drawable/map_icon_destination" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
<!--加载动画-->
<RelativeLayout
android:id="@+id/loading_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@+id/data_container"
android:visibility="gone"
>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:alpha="0.8"
android:background="@color/white">
</FrameLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/loading_icon"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"
/>
<ProgressBar
android:id="@+id/progress_bar_tv"
android:layout_width="65dp"
android:layout_height="65dp"
android:layout_centerVertical="true"
android:indeterminateBehavior="repeat"
android:indeterminateDrawable="@drawable/loading_circle"
android:indeterminateOnly="true"
android:visibility="visible"
android:layout_centerHorizontal="true"
/>
<!--<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_centerInParent="true"
android:layout_below="@+id/progress_bar_tv"
android:text="@string/breaking_and_wait"
android:textColor="@color/loading_color"
android:textSize="@dimen/font_size_15" />-->
</RelativeLayout>
</RelativeLayout>
<LinearLayout
android:layout_width="120dp"
android:layout_height="match_parent"
android:layout_gravity="end"
android:layout_marginTop="60dp"
android:background="@color/white"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="48dp"
android:gravity="center"
android:text="@string/choose_vehicle"
android:textColor="@color/black"
android:textSize="@dimen/font_size_15" />
<View
android:layout_width="match_parent"
android:layout_height="10px"
android:background="@color/list_view_divider" />
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cacheColorHint="#00000000"
android:divider="@color/list_view_divider"
android:dividerHeight="5dp"
android:fadingEdge="vertical"
android:fastScrollEnabled="false"
android:footerDividersEnabled="false"
android:headerDividersEnabled="false"
android:smoothScrollbar="true" />
</LinearLayout>
</LinearLayout>
json格式的文件(就是activity中提到的baiduTrack.json文件)
{"code":"","msg":"","data":["{\"status\":0,\"message\":\"成功\",\"total\":183,\"distance\":41420.454952368,\"toll_distance\":21768.874985325,\"low_speed_distance\":0,\"points\":[{\"loc_time\":1583399038,\"latitude\":23.162981209863,\"longitude\":113.5183105882,\"speed\":1.9704359414511,\"direction\":145.03425049045},{\"loc_time\":1583399135,\"latitude\":23.162324822703,\"longitude\":113.51879195379,\"speed\":17.965209268279,\"direction\":185.4958739896},{\"loc_time\":1583399135,\"latitude\":23.162170679943,\"longitude\":113.51877582246,\"speed\":17.965209268279,\"direction\":222.37891592352},{\"loc_time\":1583399169,\"latitude\":23.1617163099,\"longitude\":113.51791965633,\"speed\":2.7302969550567,\"direction\":295.10304896885},{\"loc_time\":1583399304,\"latitude\":23.162867515118,\"longitude\":113.51704924914,\"speed\":34.332919517071,\"direction\":356.81922729711},{\"loc_time\":1583399304,\"latitude\":23.163032010594,\"longitude\":113.51710432024,\"speed\":34.332919517071,\"direction\":54.249047444041},{\"loc_time\":1583399304,\"latitude\":23.16340163623,\"longitude\":113.51766276092,\"speed\":34.332919517071,\"direction\":322.15069841506},{\"loc_time\":1583399304,\"latitude\":23.1636926859,\"longitude\":113.51741246778,\"speed\":34.332919517071,\"direction\":54.776286069662},{\"loc_time\":1583399304,\"latitude\":23.166000658471,\"longitude\":113.52097400499,\"speed\":34.332919517071,\"direction\":68.039713189313},{\"loc_time\":1583399304,\"latitude\":23.166661052635,\"longitude\":113.52267619335,\"speed\":34.332919517071,\"direction\":91.207580714705},{\"loc_time\":1583399304,\"latitude\":23.166655039988,\"longitude\":113.52297098462,\"speed\":34.332919517071,\"direction\":74.889498426869},{\"loc_time\":1583399397,\"latitude\":23.167113616486,\"longitude\":113.52489553571,\"speed\":32.097889575864,\"direction\":71.829125023764},{\"loc_time\":1583399420,\"latitude\":23.167661822772,\"longitude\":113.52660487272,\"speed\":21.344933773378,\"direction\":135.0589707347},{\"loc_time\":1583399449,\"latitude\":23.16548946239,\"longitude\":113.52893624947,\"speed\":37.847819822382,\"direction\":124.87140712623},{\"loc_time\":1583399449,\"latitude\":23.165153976858,\"longitude\":113.52948419739,\"speed\":37.847819822382,\"direction\":137.30195481465},{\"loc_time\":1583399449,\"latitude\":23.163801445183,\"longitude\":113.53073069295,\"speed\":37.847819822382,\"direction\":146.23050869127},{\"loc_time\":1583399449,\"latitude\":23.16228116034,\"longitude\":113.53163497605,\"speed\":37.847819822382,\"direction\":159.06793377491},{\"loc_time\":1583399449,\"latitude\":23.160993293862,\"longitude\":113.5321522328,\"speed\":37.847819822382,\"direction\":163.88213698104},{\"loc_time\":1583399449,\"latitude\":23.160120875115,\"longitude\":113.53238363609,\"speed\":37.847819822382,\"direction\":170.15279090211},{\"loc_time\":1583399449,\"latitude\":23.157268664264,\"longitude\":113.53285049657,\"speed\":37.847819822382,\"direction\":174.5297098459},{\"loc_time\":1583399449,\"latitude\":23.156201744204,\"longitude\":113.53280248365,\"speed\":37.847819822382,\"direction\":192.16149216075},{\"loc_time\":1583399449,\"latitude\":23.15555077287,\"longitude\":113.53260268045,\"speed\":37.847819822382,\"direction\":204.3163658703},{\"loc_time\":1583399449,\"latitude\":23.153833328637,\"longitude\":113.53167724688,\"speed\":37.847819822382,\"direction\":209.27214190257},{\"loc_time\":1583399449,\"latitude\":23.153328880903,\"longitude\":113.53132750687,\"speed\":37.847819822382,\"direction\":218.87579258447},{\"loc_time\":1583399449,\"latitude\":23.152357452816,\"longitude\":113.5304209881,\"speed\":37.847819822382,\"direction\":204.99670303117},{\"loc_time\":1583399449,\"latitude\":23.151859239325,\"longitude\":113.53018043694,\"speed\":37.847819822382,\"direction\":195.93493922138},{\"loc_time\":1583399449,\"latitude\":23.151305500481,\"longitude\":113.53007996114,\"speed\":37.847819822382,\"direction\":179.54975783186},{\"loc_time\":1583399449,\"latitude\":23.15048122781,\"longitude\":113.53012441097,\"speed\":37.847819822382,\"direction\":173.10272815816},{\"loc_time\":1583399449,\"latitude\":23.149151141542,\"longitude\":113.53037871505,\"speed\":37.847819822382,\"direction\":150.49499844661},{\"loc_time\":1583399449,\"latitude\":23.148626742375,\"longitude\":113.53072666039,\"speed\":37.847819822382,\"direction\":131.91670589797},{\"loc_time\":1583399449,\"latitude\":23.148404609413,\"longitude\":113.53099575145,\"speed\":37.847819822382,\"direction\":118.73487151249},{\"loc_time\":1583399449,\"latitude\":23.148183933337,\"longitude\":113.53158516133,\"speed\":37.847819822382,\"direction\":94.470359767506},{\"loc_time\":1583399653,\"latitude\":23.14826716477,\"longitude\":113.53424443876,\"speed\":12.021108698947,\"direction\":92.495390802844},{\"loc_time\":1583399653,\"latitude\":23.148238342474,\"longitude\":113.5346329981,\"speed\":12.021108698947,\"direction\":103.22457320961},{\"loc_time\":1583399681,\"latitude\":23.148073084388,\"longitude\":113.53518676677,\"speed\":14.8802858657,\"direction\":95.52115012411},{\"loc_time\":1583399681,\"latitude\":23.148138326596,\"longitude\":113.53553137105,\"speed\":14.8802858657,\"direction\":32.057014194984},{\"loc_time\":1583399681,\"latitude\":23.148244847107,\"longitude\":113.53559153523,\"speed\":14.8802858657,\"direction\":336.84985530828},{\"loc_time\":1583399681,\"latitude\":23.149233096039,\"longitude\":113.53520450818,\"speed\":14.8802858657,\"direction\":346.34324804698},{\"loc_time\":1583399750,\"latitude\":23.150704939569,\"longitude\":113.53483306171,\"speed\":66.432999082979,\"direction\":280.08973641095},{\"loc_time\":1583400030,\"latitude\":23.158843612527,\"longitude\":113.48508972352,\"speed\":79.146881275283,\"direction\":290.74518949722},{\"loc_time\":1583400040,\"latitude\":23.159600453448,\"longitude\":113.48272874135,\"speed\":88.987410059891,\"direction\":287.86178323893},{\"loc_time\":1583400040,\"latitude\":23.160300867479,\"longitude\":113.48020593536,\"speed\":88.987410059891,\"direction\":285.35445006762},{\"loc_time\":1583400059,\"latitude\":23.160928788632,\"longitude\":113.4774785491,\"speed\":91.856984275663,\"direction\":282.36719785897},{\"loc_time\":1583400059,\"latitude\":23.161387677458,\"longitude\":113.47503435825,\"speed\":91.856984275663,\"direction\":279.76342983325},{\"loc_time\":1583400152,\"latitude\":23.164040851946,\"longitude\":113.45814013803,\"speed\":104.21870176093,\"direction\":278.07769433886},{\"loc_time\":1583400162,\"latitude\":23.164420039071,\"longitude\":113.45487855572,\"speed\":125.51493184798,\"direction\":275.7431200208},{\"loc_time\":1583400162,\"latitude\":23.164671462773,\"longitude\":113.45176055685,\"speed\":125.51493184798,\"direction\":273.75227149299},{\"loc_time\":1583400162,\"latitude\":23.164809968038,\"longitude\":113.44873439398,\"speed\":125.51493184798,\"direction\":271.69742251431},{\"loc_time\":1583400214,\"latitude\":23.165109701668,\"longitude\":113.43746359905,\"speed\":105.35890972817,\"direction\":269.45133703821},{\"loc_time\":1583400229,\"latitude\":23.164985134107,\"longitude\":113.43370883144,\"speed\":82.818277121804,\"direction\":265.7464824944},{\"loc_time\":1583400243,\"latitude\":23.164692446988,\"longitude\":113.43044196124,\"speed\":78.703515857804,\"direction\":262.44660333588},{\"loc_time\":1583400258,\"latitude\":23.164034205797,\"longitude\":113.42610194307,\"speed\":75.318254237498,\"direction\":258.03585220452},{\"loc_time\":1583400281,\"latitude\":23.163051682242,\"longitude\":113.4217824915,\"speed\":53.884835459714,\"direction\":253.54928258048},{\"loc_time\":1583400299,\"latitude\":23.162087767777,\"longitude\":113.41849866507,\"speed\":55.089942044814,\"direction\":251.27760662131},{\"loc_time\":1583400355,\"latitude\":23.159311711903,\"longitude\":113.40972253005,\"speed\":57.819775495139,\"direction\":252.55277446174},{\"loc_time\":1583400355,\"latitude\":23.159109911165,\"longitude\":113.40888387809,\"speed\":57.819775495139,\"direction\":260.6004225747},{\"loc_time\":1583400417,\"latitude\":23.158503903957,\"longitude\":113.40185571517,\"speed\":49.732489453861,\"direction\":261.82826528758},{\"loc_time\":1583400417,\"latitude\":23.158361521034,\"longitude\":113.40132806477,\"speed\":49.732489453861,\"direction\":266.29694695985},{\"loc_time\":1583400485,\"latitude\":23.157406530732,\"longitude\":113.39072603522,\"speed\":52.181063729218,\"direction\":265.11553291043},{\"loc_time\":1583400504,\"latitude\":23.157342783724,\"longitude\":113.38926902472,\"speed\":55.732593494325,\"direction\":279.23971566515},{\"loc_time\":1583400514,\"latitude\":23.157419312627,\"longitude\":113.38873963024,\"speed\":29.729251239863,\"direction\":279.61171779071},{\"loc_time\":1583400525,\"latitude\":23.157842682026,\"longitude\":113.38712988468,\"speed\":108.91337776256,\"direction\":293.99298538097},{\"loc_time\":1583400525,\"latitude\":23.158154239149,\"longitude\":113.38644432948,\"speed\":108.91337776256,\"direction\":300.44950791765},{\"loc_time\":1583400525,\"latitude\":23.158630095325,\"longitude\":113.38566328733,\"speed\":108.91337776256,\"direction\":308.24517593253},{\"loc_time\":1583400538,\"latitude\":23.159713759394,\"longitude\":113.38432674561,\"speed\":76.631764311082,\"direction\":315.51562461077},{\"loc_time\":1583400538,\"latitude\":23.166315392386,\"longitude\":113.37674243507,\"speed\":76.631764311082,\"direction\":309.86987360779},{\"loc_time\":1583400592,\"latitude\":23.167153085438,\"longitude\":113.37554070537,\"speed\":27.088470326807,\"direction\":302.73090259713},{\"loc_time\":1583400616,\"latitude\":23.167842800289,\"longitude\":113.37422522244,\"speed\":119.63317853209,\"direction\":294.83141638579},{\"loc_time\":1583400616,\"latitude\":23.168458362595,\"longitude\":113.37266251139,\"speed\":119.63317853209,\"direction\":290.99729627629},{\"loc_time\":1583400629,\"latitude\":23.169078389788,\"longitude\":113.37080773393,\"speed\":72.400981825585,\"direction\":287.020435896},{\"loc_time\":1583400629,\"latitude\":23.169530645641,\"longitude\":113.36891073007,\"speed\":72.400981825585,\"direction\":281.25429324893},{\"loc_time\":1583400645,\"latitude\":23.16979285321,\"longitude\":113.36731030286,\"speed\":75.142197517085,\"direction\":276.34698529325},{\"loc_time\":1583400650,\"latitude\":23.169965578358,\"longitude\":113.36479334554,\"speed\":73.734854164121,\"direction\":275.97906319817},{\"loc_time\":1583400664,\"latitude\":23.170226624336,\"longitude\":113.36234259273,\"speed\":91.625445480706,\"direction\":281.66331755165},{\"loc_time\":1583400673,\"latitude\":23.170708525823,\"longitude\":113.3602364546,\"speed\":74.213469151744,\"direction\":292.10132361966},{\"loc_time\":1583400684,\"latitude\":23.171614523911,\"longitude\":113.3581181116,\"speed\":77.340782613906,\"direction\":298.26735857332},{\"loc_time\":1583400738,\"latitude\":23.175918293412,\"longitude\":113.34923086251,\"speed\":80.443267506063,\"direction\":291.50899639234},{\"loc_time\":1583400738,\"latitude\":23.17620053008,\"longitude\":113.34834748405,\"speed\":80.443267506063,\"direction\":284.42643537991},{\"loc_time\":1583400747,\"latitude\":23.176361505182,\"longitude\":113.34750584165,\"speed\":61.641324870852,\"direction\":277.373231788},{\"loc_time\":1583400756,\"latitude\":23.176426121824,\"longitude\":113.34664697953,\"speed\":63.675332851144,\"direction\":269.6935725742}"],"success":true}
补充一下json格式的解析方式
public static ArrayList<?> MultipleJson(String json, Class T) {
try {
if (TextUtils.isEmpty(json))
return null;
Gson gson = new Gson();
Map map = gson.fromJson(json,Map.class);
ArrayList<BaiduTrack> xylist = new ArrayList<>();
JsonParser parser = new JsonParser();
JsonArray Jarray = parser.parse(map.get("data").toString()).getAsJsonArray();
for(int i = 0;i < Jarray.size(); i++){
JsonArray jsonArray = Jarray.get(i).getAsJsonObject().get("points").getAsJsonArray();
// JsonArray jsonArray = parser.parse(point.get("points").toString()).getAsJsonArray();
xylist.addAll(gson.fromJson(jsonArray.toString(), new TypeToken<ArrayList<BaiduTrack>>() {}.getType()));
}
LogUtils.i(TAG,"经纬度的长度"+xylist.size());
return xylist;
} catch (Exception e) {
LogUtils.e(TAG, "dealwithJson-error=" + e.toString());
}
return null;
}
map_bullet_box.xml文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="@drawable/map_infowindow_bg">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_marginTop="8dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/font_color"
android:text="@string/speed_per_hour"
android:textSize="@dimen/font_size_13"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/font_color"
android:text="@string/colon"
android:textSize="@dimen/font_size_13"/>
<TextView
android:id="@+id/speed_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/app_title"
android:textSize="@dimen/font_size_13" />
</LinearLayout>
<TextView
android:id="@+id/time_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textColor="@color/font_color"
android:textSize="@dimen/font_size_13"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:text="2020-03-07 18:06:53"/>
</LinearLayout>
BackTrack类
package com.boxin.truck.model;
import java.util.List;
/**
* @author lsx
* @time 2020/4/20 17:06
*/
public class BaiduTrack extends BaseModel{
private double longitude;//经度
private double latitude;//纬度
private double speed;//速度
private long loc_time;//定位时的设备时间
private double direction;//方向
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public double getSpeed() {
return speed;
}
public void setSpeed(double speed) {
this.speed = speed;
}
public long getLoc_time() {
return loc_time;
}
public void setLoc_time(long loc_time) {
this.loc_time = loc_time;
}
public double getDirection() {
return direction;
}
public void setDirection(double direction) {
this.direction = direction;
}
}