1、​​酷跑项目:崩溃自动重启功能​​​ 2、​​酷跑项目:首页跳转+底部菜单联动​​ 3、​​酷跑项目:百度地图获取定位​

实现倒计时功能
【达内课程】酷跑项目:模拟路线和显示数据_ide
fragment_sport.xml中放置一个按钮,点击按钮实现倒计时功能

SportFragment中关键代码如下

int count = 3;
AlertDialog alertDialog;
Handler handler = new Handler();
private TextView tvAction;

@Override
public void onClick(View view) {
switch (view.getId()){
//点击图中按钮实现倒计时
case R.id.relativeLayout_startSport:
alertDialog = new AlertDialog.Builder(getActivity()).create();
View dialogView = View.inflate(getActivity(),R.layout.activity_show_counter,null);
tvAction = dialogView.findViewById(R.id.tv_show_count);
alertDialog.setView(dialogView);

handler.postDelayed(new Runnable() {
@Override
public void run() {
count--;
if(count<1){
alertDialog.dismiss();
alertDialog = null;
count = 3;
}else {
tvAction.setText(String.valueOf(count));
handler.postDelayed(this,1000);
}
}
},1000);

alertDialog.show();
break;
}
}

其中activity_show_counter是弹出的倒计时的布局

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/title_bg_green"
>

<TextView
android:layout_margin="96dp"
android:id="@+id/tv_show_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:textSize="@dimen/text_count_size"
android:textColor="@android:color/white"
android:text="3" />

</RelativeLayout>

绘制

【达内课程】酷跑项目:模拟路线和显示数据_sed_02
根据​​​绘制线​​来完成绘制

//放线的坐标
ArrayList<LatLng> pointsList = new ArrayList<LatLng>();

class MyLocationListener extends BDAbstractLocationListener {

@Override
public void onReceiveLocation(BDLocation bdLocation) {
......

//在地图上单击
mBaiduMap.setOnMapClickListener(new BaiduMap.OnMapClickListener() {
@Override
public void onMapClick(LatLng latLng) {
//之前单击绘制点的代码先注释掉
......

//用户在跑步,跑步时得到坐标,模拟得到坐标
mBaiduMap.clear();
pointsList.add(latLng);
//画线
if (pointsList.size() >= 2) {
//设置折线的属性
PolylineOptions mOverlayOptions = new PolylineOptions();
mOverlayOptions.points(pointsList);
//在地图上绘制折线
mBaiduMap.addOverlay(mOverlayOptions);
}
}

@Override
public boolean onMapPoiClick(MapPoi mapPoi) {
return false;
}
});
}
}

显示数据
【达内课程】酷跑项目:模拟路线和显示数据_sed_03

fragment_sport中引入fragment_sport_recorder

fragment_sport_recorder

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@android:color/white"
android:orientation="vertical">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="vertical">

<TextView
android:id="@+id/tv_distance"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0.00"
android:textColor="@android:color/black"
android:textSize="@dimen/text_recoder_distance_size" />

<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="距离(公里)"
android:textColor="@android:color/black"
android:textSize="@dimen/text_recoder_name_size" />
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/gray_normal"></LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/activity_bg"
android:orientation="horizontal">

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">

<Chronometer
android:id="@+id/chronometer1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Chronometer" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="时长"
android:textColor="@android:color/black"
android:textSize="@dimen/text_recoder_name_size" />
</LinearLayout>

<LinearLayout
android:layout_width="1px"
android:layout_height="match_parent"
android:background="@color/gray_normal"
android:orientation="vertical"></LinearLayout>

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:orientation="vertical">

<TextView
android:id="@+id/tv_recorder_speed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="0.00"
android:textColor="@android:color/black"
android:textSize="@dimen/text_recoder_time_size" />

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="时速(公里/时)"
android:textColor="@android:color/black"
android:textSize="@dimen/text_recoder_name_size" />
</LinearLayout>
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="1px"
android:background="@color/gray_normal" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="@dimen/margin"
android:background="@color/activity_bg" />
</LinearLayout>

SportFragment中关键代码

public class SportFragment extends Fragment implements View.OnClickListener {
......
//显示统计界面
LinearLayout recorderLinearLayout;
//更新统计数据
Runnable updateDataRunnable;
Chronometer chronometer;
......
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.relativeLayout_startSport:
alertDialog = new AlertDialog.Builder(getActivity()).create();
View dialogView = View.inflate(getActivity(), R.layout.activity_show_counter, null);
tvAction = dialogView.findViewById(R.id.tv_show_count);
alertDialog.setView(dialogView);

if (tvButton.getText().toString().equals("开始")) {

handler.postDelayed(new Runnable() {
@Override
public void run() {
count--;
if (count < 1) {
alertDialog.dismiss();
alertDialog = null;
count = 3;
tvButton.setText("结束");
showRecordder();
} else {
tvAction.setText(String.valueOf(count));
handler.postDelayed(this, 1000);
}
}
}, 1000);

alertDialog.show();
}else if(tvButton.getText().toString().equals("结束")){
tvButton.setText("开始");
recorderLinearLayout.setVisibility(View.GONE);
pointsList.clear();
mBaiduMap.clear();
//前面执行handler.post(runnable)
//必须移除
handler.removeCallbacks(updateDataRunnable);
}
break;
}
}

private void showRecordder() {
recorderLinearLayout.setVisibility(View.VISIBLE);
tvDistance.setText("0.00");
tvRecorderSpeed.setText("0.00");

chronometer.setBase(SystemClock.elapsedRealtime());
chronometer.start();

updateDataRunnable = new Runnable() {
@Override
public void run() {
try {
if (pointsList.size() >= 2) {
//更新公里
double distance = 0;
//list[0] 112,39
//list[1] 113,39
//list[2] 114,39
for (int i = 0; i < pointsList.size() - 1; i++) {
double lon1 = pointsList.get(i).longitude;
double lat1 = pointsList.get(i).latitude;

double lon2 = pointsList.get(i + 1).longitude;
double lat2 = pointsList.get(i + 1).latitude;

distance = distance + BaiduMapUtil.GetDistance(lon1, lat1, lon2, lat2);
}
//算出的结果是米
distance = distance / 1000;
String strDistance = String.valueOf(distance);
//1.06839233
if (strDistance.contains(".")) {
int pointPosition = strDistance.indexOf(".");
strDistance = strDistance.substring(0, pointPosition + 3);
}
tvDistance.setText(strDistance);

//更新速度
String showTime = chronometer.getText().toString();
double hour = 0, minute = 0, second = 0;
String strMinute = showTime.split(":")[0];
minute = Double.parseDouble(strMinute);

String strSecond = showTime.split(":")[1];
second = Double.parseDouble(strSecond);

hour = (minute * 60 + second) / 60 / 60;

double speed = distance/hour;
String strSpeed = String.valueOf(speed);
//12.345
//.position 2
//0,5 保留2位
if(strSpeed.contains(".")){
int pointPosition = strSpeed.indexOf(".");
strSpeed = strSpeed.substring(0,pointPosition+3);
}

tvRecorderSpeed.setText(strSpeed);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
//再次调用run
handler.postDelayed(this, 2000);
}
}
};
//updateDataRunnable不停运行
handler.post(updateDataRunnable);
}

其中BaiduMapUtil是计算距离的工具类

public class BaiduMapUtil {
static final double DEF_PI = 3.14159265359; // PI
static final double DEF_2PI = 6.28318530712; // 2*PI
static final double DEF_PI180 = 0.01745329252; // PI/180.0
static final double DEF_R = 6370693.5; // radius of earth

/**
* 计算距离
*
* @param lon1
* @param lat1
* @param lon2
* @param lat2
* @return
*/
public static double GetDistance
(double lon1, double lat1, double lon2, double lat2) {
double ew1, ns1, ew2, ns2;
double dx, dy, dew;
double distance;

ew1 = lon1 * DEF_PI180;
ns1 = lat1 * DEF_PI180;
ew2 = lon2 * DEF_PI180;
ns2 = lat2 * DEF_PI180;

dew = ew1 - ew2;

if (dew > DEF_PI)
dew = DEF_2PI - dew;
else if (dew < -DEF_PI)
dew = DEF_2PI + dew;
dx = DEF_R * Math.cos(ns1) * dew;
dy = DEF_R * (ns1 - ns2);

distance = Math.sqrt(dx * dx + dy * dy);
return distance;
}
}

?​​Android Chronometer​