最初的app
15
.gitignore
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
*.iml
|
||||
.gradle
|
||||
/local.properties
|
||||
/.idea/caches
|
||||
/.idea/libraries
|
||||
/.idea/modules.xml
|
||||
/.idea/workspace.xml
|
||||
/.idea/navEditor.xml
|
||||
/.idea/assetWizardSettings.xml
|
||||
.DS_Store
|
||||
/build
|
||||
/captures
|
||||
.externalNativeBuild
|
||||
.cxx
|
||||
local.properties
|
||||
3
.idea/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
6
.idea/compiler.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CompilerConfiguration">
|
||||
<bytecodeTargetLevel target="17" />
|
||||
</component>
|
||||
</project>
|
||||
13
.idea/deploymentTargetDropDown.xml
generated
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="deploymentTargetDropDown">
|
||||
<value>
|
||||
<entry key="MainActivity">
|
||||
<State />
|
||||
</entry>
|
||||
<entry key="app">
|
||||
<State />
|
||||
</entry>
|
||||
</value>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/encodings.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding" defaultCharsetForPropertiesFiles="UTF-8">
|
||||
<file url="PROJECT" charset="UTF-8" />
|
||||
</component>
|
||||
</project>
|
||||
19
.idea/gradle.xml
generated
Normal file
@@ -0,0 +1,19 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GradleMigrationSettings" migrationVersion="1" />
|
||||
<component name="GradleSettings">
|
||||
<option name="linkedExternalProjectsSettings">
|
||||
<GradleProjectSettings>
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="gradleJvm" value="#GRADLE_LOCAL_JAVA_HOME" />
|
||||
<option name="modules">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
<option value="$PROJECT_DIR$/app" />
|
||||
</set>
|
||||
</option>
|
||||
<option name="resolveExternalAnnotations" value="false" />
|
||||
</GradleProjectSettings>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
10
.idea/migrations.xml
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectMigrations">
|
||||
<option name="MigrateToGradleLocalJavaHome">
|
||||
<set>
|
||||
<option value="$PROJECT_DIR$" />
|
||||
</set>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
17
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
<option name="id" value="Android" />
|
||||
</component>
|
||||
<component name="VisualizationToolProject">
|
||||
<option name="state">
|
||||
<ProjectState>
|
||||
<option name="scale" value="0.7879616963064295" />
|
||||
</ProjectState>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
1
app/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
/build
|
||||
76
app/build.gradle
Normal file
@@ -0,0 +1,76 @@
|
||||
plugins {
|
||||
alias(libs.plugins.androidApplication)
|
||||
}
|
||||
|
||||
android {
|
||||
namespace 'com.example.mangowalking'
|
||||
compileSdk 34
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.example.mangowalking"
|
||||
minSdk 24
|
||||
targetSdk 34
|
||||
versionCode 1
|
||||
versionName "1.0"
|
||||
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
ndk {
|
||||
//设置支持的SO库架构(开发者可以根据需要,选择一个或多个平台的so)
|
||||
abiFilters "armeabi", "armeabi-v7a", "arm64-v8a", "x86","x86_64"
|
||||
}
|
||||
|
||||
}
|
||||
sourceSets {
|
||||
main {
|
||||
jniLibs.srcDirs = ['libs']
|
||||
}
|
||||
debug.setRoot('build-types/debug')
|
||||
release.setRoot('build-types/release')
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
buildFeatures {
|
||||
viewBinding true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 构建时间
|
||||
def generateTime(){
|
||||
return new Date().format("yyyy_MM_dd_HH_mm_ss")
|
||||
}
|
||||
|
||||
|
||||
// 自定义打包名称
|
||||
android.applicationVariants.all { variant ->
|
||||
variant.outputs.all {
|
||||
outputFileName = "ManGoWalk_v${versionName}_${generateTime()}.apk"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation libs.appcompat
|
||||
implementation libs.material
|
||||
implementation libs.activity
|
||||
implementation libs.constraintlayout
|
||||
// implementtation 'cn.shanyaliux.serialport:serialport:4.2.0'
|
||||
// implementation 'com.amap.api:3dmap-location-search:latest.integration'
|
||||
// implementation 'com.amap.api:3dmap:latest.integration'
|
||||
// implementation 'com.amap.api:location:6.4.9'
|
||||
testImplementation libs.junit
|
||||
androidTestImplementation libs.ext.junit
|
||||
androidTestImplementation libs.espresso.core
|
||||
}
|
||||
BIN
app/libs/arm64-v8a/libAMapSDK_MAP_v10_1_200.so
Normal file
BIN
app/libs/armeabi-v7a/libAMapSDK_MAP_v10_1_200.so
Normal file
10
app/libs/build.properties
Normal file
@@ -0,0 +1,10 @@
|
||||
iid=11600
|
||||
sid=3528001
|
||||
bid=1350002
|
||||
version=13.08.0.10009081
|
||||
time=2025-03-17 18:00:51
|
||||
FEATURE_LOCATION=1
|
||||
FEATURE_ROUTE_OVERLAY=1
|
||||
FEATURE_MVT=1
|
||||
FEATURE_3DTiles=1
|
||||
FEATURE_GLTF=1
|
||||
22
app/proguard-rules.pro
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
||||
|
||||
BIN
app/release/ManGoWalk_v1.0_2025_04_17_19_59_18.apk
Normal file
37
app/release/output-metadata.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"version": 3,
|
||||
"artifactType": {
|
||||
"type": "APK",
|
||||
"kind": "Directory"
|
||||
},
|
||||
"applicationId": "com.example.mangowalking",
|
||||
"variantName": "release",
|
||||
"elements": [
|
||||
{
|
||||
"type": "SINGLE",
|
||||
"filters": [],
|
||||
"attributes": [],
|
||||
"versionCode": 1,
|
||||
"versionName": "1.0",
|
||||
"outputFile": "ManGoWalk_v1.0_2025_04_17_19_59_18.apk"
|
||||
}
|
||||
],
|
||||
"elementType": "File",
|
||||
"baselineProfiles": [
|
||||
{
|
||||
"minApi": 28,
|
||||
"maxApi": 30,
|
||||
"baselineProfiles": [
|
||||
"baselineProfiles/1/ManGoWalk_v1.0_2025_04_17_19_59_18.dm"
|
||||
]
|
||||
},
|
||||
{
|
||||
"minApi": 31,
|
||||
"maxApi": 2147483647,
|
||||
"baselineProfiles": [
|
||||
"baselineProfiles/0/ManGoWalk_v1.0_2025_04_17_19_59_18.dm"
|
||||
]
|
||||
}
|
||||
],
|
||||
"minSdkVersionForDexing": 24
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.example.mangowalking;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Instrumented test, which will execute on an Android device.
|
||||
*
|
||||
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class ExampleInstrumentedTest {
|
||||
@Test
|
||||
public void useAppContext() {
|
||||
// Context of the app under test.
|
||||
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
|
||||
assertEquals("com.example.mangowalking", appContext.getPackageName());
|
||||
}
|
||||
}
|
||||
65
app/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- 用于进行网络定位 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> <!-- 用于访问GPS定位 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> <!-- 用于获取运营商信息,用于支持提供运营商信息相关的接口 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> <!-- 用于访问wifi网络信息,wifi信息会用于进行网络定位 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" /> <!-- 用于获取wifi的获取权限,wifi信息会用来进行网络定位 -->
|
||||
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" /> <!-- 用于访问网络,网络定位需要上网 -->
|
||||
<uses-permission android:name="android.permission.INTERNET" /> <!-- 用于写入缓存数据到扩展存储卡 -->
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <!-- 用于申请调用A-GPS模块 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS" /> <!-- 如果设置了target >= 28 如果需要启动后台定位则必须声明这个权限 -->
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <!-- 如果您的应用需要后台定位权限,且有可能运行在Android Q设备上,并且设置了target>28,必须增加这个权限声明 -->
|
||||
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> <!-- 允许写设备缓存,用于问题排查 -->
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_SETTINGS"
|
||||
tools:ignore="ProtectedPermissions" /> <!-- 允许读设备等信息,用于问题排查 -->
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
|
||||
<!-- 添加 BLE权限 -->
|
||||
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
|
||||
<!-- 操纵蓝牙的开启-->
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
|
||||
<uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE" />
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.bluetooth_le"
|
||||
android:required="true" />
|
||||
|
||||
<application
|
||||
android:name=".App"
|
||||
android:allowBackup="true"
|
||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
||||
android:fullBackupContent="@xml/backup_rules"
|
||||
android:icon="@mipmap/ic_my"
|
||||
android:label="@string/app_name"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.ManGoWalking"
|
||||
tools:targetApi="31">
|
||||
<activity
|
||||
android:name=".RouteDetailActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".RouteActivity"
|
||||
android:exported="false" />
|
||||
<activity
|
||||
android:name=".MainActivity"
|
||||
android:exported="true"
|
||||
android:hardwareAccelerated="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity> <!-- 高德定位服务 -->
|
||||
<service android:name="com.amap.api.location.APSService" /> <!-- 高德的Key value里面的值请使用自己的Key -->
|
||||
<meta-data
|
||||
android:name="com.amap.api.v2.apikey"
|
||||
android:value="14f8203a16e09d7000bd8b31c9bf1ef7" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
27
app/src/main/java/com/example/mangowalking/App.java
Normal file
@@ -0,0 +1,27 @@
|
||||
package com.example.mangowalking;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
import com.amap.api.location.AMapLocationClient;
|
||||
import com.amap.api.maps.MapsInitializer;
|
||||
import com.amap.api.services.core.ServiceSettings;
|
||||
|
||||
public class App extends Application {
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
Context mContext = this;
|
||||
// 定位隐私政策同意
|
||||
AMapLocationClient.updatePrivacyShow(mContext,true,true);
|
||||
AMapLocationClient.updatePrivacyAgree(mContext,true);
|
||||
// 地图隐私政策同意
|
||||
MapsInitializer.updatePrivacyShow(mContext,true,true);
|
||||
MapsInitializer.updatePrivacyAgree(mContext,true);
|
||||
// 搜索隐私政策同意
|
||||
ServiceSettings.updatePrivacyShow(mContext,true,true);
|
||||
ServiceSettings.updatePrivacyAgree(mContext,true);
|
||||
}
|
||||
}
|
||||
|
||||
635
app/src/main/java/com/example/mangowalking/MainActivity.java
Normal file
@@ -0,0 +1,635 @@
|
||||
package com.example.mangowalking;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.Color;
|
||||
import android.os.Bundle;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.ForegroundColorSpan;
|
||||
import android.util.Log;
|
||||
import android.Manifest; // 针对于ACCESS_FINE_LOCATION
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.animation.LinearInterpolator;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
|
||||
import com.amap.api.location.AMapLocation;
|
||||
import com.amap.api.location.AMapLocationClient;
|
||||
import com.amap.api.location.AMapLocationClientOption;
|
||||
import com.amap.api.location.AMapLocationListener;
|
||||
import com.amap.api.maps.AMap;
|
||||
import com.amap.api.maps.CameraUpdate;
|
||||
import com.amap.api.maps.CameraUpdateFactory;
|
||||
import com.amap.api.maps.LocationSource;
|
||||
import com.amap.api.maps.UiSettings;
|
||||
import com.amap.api.maps.model.BitmapDescriptorFactory;
|
||||
import com.amap.api.maps.model.CameraPosition;
|
||||
import com.amap.api.maps.model.LatLng;
|
||||
import com.amap.api.maps.model.Marker;
|
||||
import com.amap.api.maps.model.MarkerOptions;
|
||||
import com.amap.api.maps.model.MyLocationStyle;
|
||||
import com.amap.api.maps.model.animation.Animation;
|
||||
import com.amap.api.maps.model.animation.RotateAnimation;
|
||||
import com.amap.api.services.core.AMapException;
|
||||
import com.amap.api.services.core.LatLonPoint;
|
||||
import com.amap.api.services.core.PoiItem;
|
||||
import com.amap.api.services.geocoder.GeocodeAddress;
|
||||
import com.amap.api.services.geocoder.GeocodeQuery;
|
||||
import com.amap.api.services.geocoder.GeocodeResult;
|
||||
import com.amap.api.services.geocoder.GeocodeSearch;
|
||||
import com.amap.api.services.geocoder.RegeocodeAddress;
|
||||
import com.amap.api.services.geocoder.RegeocodeQuery;
|
||||
import com.amap.api.services.geocoder.RegeocodeResult;
|
||||
import com.amap.api.services.poisearch.PoiResult;
|
||||
import com.amap.api.services.poisearch.PoiSearch;
|
||||
import com.example.mangowalking.databinding.ActivityMainBinding;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MainActivity extends AppCompatActivity implements AMapLocationListener, LocationSource, PoiSearch.OnPoiSearchListener, AMap.OnMapClickListener, AMap.OnMapLongClickListener, GeocodeSearch.OnGeocodeSearchListener, AMap.OnMarkerClickListener, AMap.OnMarkerDragListener, AMap.InfoWindowAdapter, AMap.OnInfoWindowClickListener {
|
||||
private static final String TAG = "MainActivity";
|
||||
private ActivityMainBinding binding;
|
||||
private ActivityResultLauncher<String> requestPermission;
|
||||
|
||||
//声明AMapLocationClient类对象
|
||||
public AMapLocationClient mLocationClient = null;
|
||||
//声明AMapLocationClientOption对象
|
||||
public AMapLocationClientOption mLocationOption = null;
|
||||
// 声明地图控制器
|
||||
private AMap aMap = null;
|
||||
// 声明地图定位监听
|
||||
private LocationSource.OnLocationChangedListener mListener = null;
|
||||
|
||||
//POI查询对象
|
||||
private PoiSearch.Query query;
|
||||
//POI搜索对象
|
||||
private PoiSearch poiSearch;
|
||||
//城市码
|
||||
private String cityCode = null;
|
||||
|
||||
//地理编码搜索
|
||||
private GeocodeSearch geocodeSearch;
|
||||
//解析成功标识码
|
||||
private static final int PARSE_SUCCESS_CODE = 1000;
|
||||
//城市
|
||||
private String city;
|
||||
|
||||
//标点列表
|
||||
private final List<Marker> markerList = new ArrayList<>();
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
requestPermission = registerForActivityResult(new ActivityResultContracts.RequestPermission(), result -> {
|
||||
// 权限申请结果
|
||||
Log.d(TAG, "权限申请结果: " + result);
|
||||
showMsg(result ? "已获取权限" : "权限申请失败");
|
||||
});
|
||||
super.onCreate(savedInstanceState);
|
||||
EdgeToEdge.enable(this);
|
||||
binding = ActivityMainBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot()); //这里要和博主一致
|
||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||
return insets;
|
||||
});
|
||||
initLocation();
|
||||
binding.mapView.onCreate(savedInstanceState);
|
||||
initMap();
|
||||
initSearch();
|
||||
initView();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化搜索
|
||||
*/
|
||||
private void initSearch() {
|
||||
// 构造 GeocodeSearch 对象
|
||||
try {
|
||||
geocodeSearch = new GeocodeSearch(this);
|
||||
// 设置监听
|
||||
geocodeSearch.setOnGeocodeSearchListener(this);
|
||||
} catch (com.amap.api.services.core.AMapException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void initLocation() {
|
||||
try {
|
||||
//初始化定位
|
||||
mLocationClient = new AMapLocationClient(getApplicationContext());
|
||||
//设置定位回调监听
|
||||
mLocationClient.setLocationListener(this);
|
||||
//初始化AMapLocationClientOption对象
|
||||
mLocationOption = new AMapLocationClientOption();
|
||||
//设置定位模式为AMapLocationMode.Hight_Accuracy,高精度模式。
|
||||
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
|
||||
//获取最近3s内精度最高的一次定位结果
|
||||
mLocationOption.setOnceLocationLatest(true);
|
||||
//设置是否返回地址信息(默认返回地址信息)
|
||||
mLocationOption.setNeedAddress(true);
|
||||
//设置定位超时时间,单位是毫秒
|
||||
mLocationOption.setHttpTimeOut(6000);
|
||||
//给定位客户端对象设置定位参数
|
||||
mLocationClient.setLocationOption(mLocationOption);
|
||||
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始定位
|
||||
*/
|
||||
private void startLocation() {
|
||||
if (mLocationClient != null) mLocationClient.startLocation();
|
||||
}
|
||||
|
||||
/**
|
||||
* 停止定位
|
||||
*/
|
||||
private void stopLocation() {
|
||||
if (mLocationClient != null) mLocationClient.stopLocation();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 初始化地图
|
||||
*/
|
||||
private void initMap() {
|
||||
if (aMap == null) {
|
||||
aMap = binding.mapView.getMap();
|
||||
// 创建定位蓝点的样式
|
||||
MyLocationStyle myLocationStyle = new MyLocationStyle();
|
||||
// 自定义定位蓝点图标
|
||||
myLocationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.drawable.gps_point));
|
||||
// 自定义精度范围的圆形边框颜色 都为0则透明
|
||||
myLocationStyle.strokeColor(Color.argb(0, 0, 0, 0));
|
||||
// 自定义精度范围的圆形边框宽度 0 无宽度
|
||||
myLocationStyle.strokeWidth(0);
|
||||
// 设置圆形的填充颜色 都为0则透明
|
||||
myLocationStyle.radiusFillColor(Color.argb(0, 0, 0, 0));
|
||||
// 设置定位蓝点的样式
|
||||
aMap.setMyLocationStyle(myLocationStyle);
|
||||
// 设置定位监听
|
||||
aMap.setLocationSource(this);
|
||||
// 设置为true表示启动显示定位蓝点,false表示隐藏定位蓝点并不进行定位,默认是false。
|
||||
aMap.setMyLocationEnabled(true);
|
||||
|
||||
aMap.setMinZoomLevel(15); //设置最小缩放等级为15 缩放等级为(3,20)
|
||||
aMap.showIndoorMap(true); //开启室内地图
|
||||
// 设置地图点击事件
|
||||
aMap.setOnMapClickListener(this);
|
||||
// 设置地图长按事件
|
||||
aMap.setOnMapLongClickListener(this);
|
||||
// 设置地图标点点击事件
|
||||
aMap.setOnMarkerClickListener(this);
|
||||
// 设置地图标点拖拽事件
|
||||
aMap.setOnMarkerDragListener(this);
|
||||
// 设置InfoWindowAdapter监听
|
||||
aMap.setInfoWindowAdapter(this);
|
||||
// 设置InfoWindow点击事件
|
||||
aMap.setOnInfoWindowClickListener(this);
|
||||
|
||||
// 地图控件设置
|
||||
UiSettings uiSettings = aMap.getUiSettings();
|
||||
// 隐藏缩放按钮
|
||||
uiSettings.setZoomControlsEnabled(false);
|
||||
// 显示比例尺,默认不显示
|
||||
uiSettings.setScaleControlsEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
// 检查是否已经获取到定位权限
|
||||
binding.mapView.onResume();
|
||||
if (checkSelfPermission(Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
|
||||
// 获取到权限
|
||||
requestPermission.launch(Manifest.permission.ACCESS_FINE_LOCATION);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
// 绑定生命周期 onPause
|
||||
binding.mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
// 绑定生命周期 onSaveInstanceState
|
||||
binding.mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
// 绑定生命周期 onDestroy
|
||||
binding.mapView.onDestroy();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 初始化定位
|
||||
*/
|
||||
|
||||
private void showMsg(CharSequence llw) {
|
||||
Toast.makeText(this, llw, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化控件
|
||||
*/
|
||||
private void initView() {
|
||||
// Poi搜索按钮点击事件
|
||||
binding.fabPoi.setOnClickListener(v -> {
|
||||
//构造query对象
|
||||
query = new PoiSearch.Query("购物", "", cityCode);
|
||||
// 设置每页最多返回多少条poiItem
|
||||
query.setPageSize(10);
|
||||
//设置查询页码
|
||||
query.setPageNum(1);
|
||||
//构造 PoiSearch 对象
|
||||
try {
|
||||
poiSearch = new PoiSearch(this, query);
|
||||
//设置搜索回调监听
|
||||
poiSearch.setOnPoiSearchListener(this);
|
||||
//发起搜索附近POI异步请求
|
||||
poiSearch.searchPOIAsyn();
|
||||
} catch (AMapException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
// 清除标点按钮点击事件
|
||||
binding.fabClearMarker.setOnClickListener(v -> clearAllMarker());
|
||||
// 路线按钮点击事件
|
||||
binding.fabRoute.setOnClickListener(v -> startActivity(new Intent(this, RouteActivity.class)));
|
||||
// 键盘按键监听
|
||||
binding.etAddress.setOnKeyListener((v, keyCode, event) -> {
|
||||
if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP) {
|
||||
//获取输入框的值
|
||||
String address = binding.etAddress.getText().toString().trim();
|
||||
if (address.isEmpty()) {
|
||||
showMsg("请输入地址");
|
||||
} else {
|
||||
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
//隐藏软键盘
|
||||
imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0);
|
||||
|
||||
// name表示地址,第二个参数表示查询城市,中文或者中文全拼,citycode、adcode
|
||||
GeocodeQuery query = new GeocodeQuery(address, city);
|
||||
geocodeSearch.getFromLocationNameAsyn(query);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 定位回调结果
|
||||
*/
|
||||
@Override
|
||||
public void onLocationChanged(AMapLocation aMapLocation) {
|
||||
if (aMapLocation == null) {
|
||||
showMsg("定位失败,aMapLocation 为空");
|
||||
return;
|
||||
}
|
||||
// 获取定位结果
|
||||
if (aMapLocation.getErrorCode() == 0) {
|
||||
// 定位成功
|
||||
showMsg("定位成功");
|
||||
// aMapLocation.getLocationType();//获取当前定位结果来源,如网络定位结果,详见定位类型表
|
||||
// aMapLocation.getLatitude();//获取纬度
|
||||
// aMapLocation.getLongitude();//获取经度
|
||||
// aMapLocation.getAccuracy();//获取精度信息
|
||||
// aMapLocation.getAddress();//详细地址,如果option中设置isNeedAddress为false,则没有此结果,网络定位结果中会有地址信息,GPS定位不返回地址信息。
|
||||
// aMapLocation.getCountry();//国家信息
|
||||
// aMapLocation.getProvince();//省信息
|
||||
// aMapLocation.getCity();//城市信息
|
||||
String result = aMapLocation.getDistrict();//城区信息
|
||||
// aMapLocation.getStreet();//街道信息
|
||||
// aMapLocation.getStreetNum();//街道门牌号信息
|
||||
// aMapLocation.getCityCode();//城市编码
|
||||
// aMapLocation.getAdCode();//地区编码
|
||||
// aMapLocation.getAoiName();//获取当前定位点的AOI信息
|
||||
// aMapLocation.getBuildingId();//获取当前室内定位的建筑物Id
|
||||
// aMapLocation.getFloor();//获取当前室内定位的楼层
|
||||
// aMapLocation.getGpsAccuracyStatus();//获取GPS的当前状态
|
||||
// 停止定位
|
||||
stopLocation();
|
||||
// 显示地图定位结果
|
||||
if (mListener != null) {
|
||||
mListener.onLocationChanged(aMapLocation);
|
||||
}
|
||||
// 显示浮动按钮
|
||||
binding.fabPoi.show();
|
||||
// 城市编码赋值
|
||||
cityCode = aMapLocation.getCityCode();
|
||||
//城市
|
||||
city = aMapLocation.getCity();
|
||||
} else {
|
||||
// 定位失败
|
||||
showMsg("定位失败,错误:" + aMapLocation.getErrorInfo());
|
||||
Log.e(TAG,"location Error, ErrCode:"
|
||||
+ aMapLocation.getErrorCode() + ", errInfo:"
|
||||
+ aMapLocation.getErrorInfo());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 激活定位
|
||||
*/
|
||||
@Override
|
||||
public void activate(OnLocationChangedListener onLocationChangedListener) {
|
||||
if (mListener == null) {
|
||||
mListener = onLocationChangedListener;
|
||||
}
|
||||
startLocation();
|
||||
}
|
||||
|
||||
/**
|
||||
* 禁用
|
||||
*/
|
||||
@Override
|
||||
public void deactivate() {
|
||||
mListener = null;
|
||||
if (mLocationClient != null) {
|
||||
mLocationClient.stopLocation();
|
||||
mLocationClient.onDestroy();
|
||||
}
|
||||
mLocationClient = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* POI搜索返回
|
||||
*
|
||||
* @param poiResult POI所有数据
|
||||
* @param i
|
||||
*/
|
||||
@Override
|
||||
public void onPoiSearched(PoiResult poiResult, int i) {
|
||||
//解析result获取POI信息
|
||||
|
||||
//获取POI组数列表
|
||||
ArrayList<PoiItem> poiItems = poiResult.getPois();
|
||||
for (PoiItem poiItem : poiItems) {
|
||||
// Log.d("MainActivity", " Title:" + poiItem.getTitle() + " Snippet:" + poiItem.getSnippet());
|
||||
Log.d("MainActivity", "Title: " + poiItem.getTitle());
|
||||
Log.d("MainActivity", "Snippet: " + poiItem.getSnippet());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* POI中的项目搜索返回
|
||||
*
|
||||
* @param poiItem 获取POI item
|
||||
* @param i
|
||||
*/
|
||||
@Override
|
||||
public void onPoiItemSearched(PoiItem poiItem, int i) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过经纬度获取地址
|
||||
* @param latLng
|
||||
*/
|
||||
private void latLonToAddress(LatLng latLng) {
|
||||
//位置点 通过经纬度进行构建
|
||||
LatLonPoint latLonPoint = new LatLonPoint(latLng.latitude, latLng.longitude);
|
||||
//逆编码查询 第一个参数表示一个Latlng,第二参数表示范围多少米,第三个参数表示是火系坐标系还是GPS原生坐标系
|
||||
RegeocodeQuery query = new RegeocodeQuery(latLonPoint, 20, GeocodeSearch.AMAP);
|
||||
//异步获取地址信息
|
||||
geocodeSearch.getFromLocationAsyn(query);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加地图标点
|
||||
*
|
||||
* @param latLng
|
||||
*/
|
||||
private void addMarker(LatLng latLng) {
|
||||
//显示浮动按钮
|
||||
binding.fabClearMarker.show();
|
||||
//添加标点
|
||||
Marker marker = aMap.addMarker(new MarkerOptions().draggable(true).position(latLng).title("标题").snippet("DefaultMarker"));
|
||||
//显示InfoWindow
|
||||
marker.showInfoWindow();
|
||||
//设置标点的绘制动画效果
|
||||
Animation animation = new RotateAnimation(marker.getRotateAngle(),marker.getRotateAngle()+360,0,0,0);
|
||||
long duration = 1000L;
|
||||
animation.setDuration(duration);
|
||||
animation.setInterpolator(new LinearInterpolator());
|
||||
|
||||
marker.setAnimation(animation);
|
||||
marker.startAnimation();
|
||||
|
||||
|
||||
|
||||
markerList.add(marker);
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空地图Marker
|
||||
*/
|
||||
public void clearAllMarker() {
|
||||
if (markerList != null && !markerList.isEmpty()) {
|
||||
for (Marker markerItem : markerList) {
|
||||
markerItem.remove();
|
||||
}
|
||||
}
|
||||
binding.fabClearMarker.hide();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 改变地图中心位置
|
||||
* @param latLng 位置
|
||||
*/
|
||||
private void updateMapCenter(LatLng latLng) {
|
||||
// CameraPosition 第一个参数: 目标位置的屏幕中心点经纬度坐标。
|
||||
// CameraPosition 第二个参数: 目标可视区域的缩放级别
|
||||
// CameraPosition 第三个参数: 目标可视区域的倾斜度,以角度为单位。
|
||||
// CameraPosition 第四个参数: 可视区域指向的方向,以角度为单位,从正北向顺时针方向计算,从0度到360度
|
||||
CameraPosition cameraPosition = new CameraPosition(latLng, 16, 30, 0);
|
||||
//位置变更
|
||||
CameraUpdate cameraUpdate = CameraUpdateFactory.newCameraPosition(cameraPosition);
|
||||
//改变位置(使用动画)
|
||||
aMap.animateCamera(cameraUpdate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 地图点击事件
|
||||
* @param latLng
|
||||
*/
|
||||
@Override
|
||||
public void onMapClick(LatLng latLng) {
|
||||
latLonToAddress(latLng);
|
||||
addMarker(latLng);
|
||||
updateMapCenter(latLng);
|
||||
}
|
||||
|
||||
/**
|
||||
* 地图长按事件
|
||||
* @param latLng
|
||||
*/
|
||||
@Override
|
||||
public void onMapLongClick(LatLng latLng) {
|
||||
latLonToAddress(latLng);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int rCode) {
|
||||
//解析result获取地址描述信息
|
||||
if(rCode == PARSE_SUCCESS_CODE){
|
||||
RegeocodeAddress regeocodeAddress = regeocodeResult.getRegeocodeAddress();
|
||||
//显示解析后的地址
|
||||
showMsg("地址:"+regeocodeAddress.getFormatAddress());
|
||||
}else {
|
||||
showMsg("获取地址失败");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGeocodeSearched(GeocodeResult geocodeResult, int rCode) {
|
||||
if (rCode != PARSE_SUCCESS_CODE) {
|
||||
showMsg("获取坐标失败");
|
||||
return;
|
||||
}
|
||||
List<GeocodeAddress> geocodeAddressList = geocodeResult.getGeocodeAddressList();
|
||||
if (geocodeAddressList != null && !geocodeAddressList.isEmpty()) {
|
||||
LatLonPoint latLonPoint = geocodeAddressList.get(0).getLatLonPoint();
|
||||
//显示解析后的坐标
|
||||
showMsg("坐标:" + latLonPoint.getLongitude() + "," + latLonPoint.getLatitude());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onMarkerClick(Marker marker) {
|
||||
if (!marker.isInfoWindowShown()) { // 显示
|
||||
marker.showInfoWindow();
|
||||
} else { // 隐藏
|
||||
marker.hideInfoWindow();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onMarkerDragStart(Marker marker) {
|
||||
Log.d(TAG, "开始拖拽");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMarkerDrag(Marker marker) {
|
||||
Log.d(TAG, "拖拽中...");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMarkerDragEnd(Marker marker) {
|
||||
showMsg("拖拽完成");
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改内容
|
||||
*
|
||||
* @param marker
|
||||
* @return
|
||||
*/
|
||||
@Override
|
||||
public View getInfoContents(Marker marker) {
|
||||
View infoContent = getLayoutInflater().inflate(
|
||||
R.layout.custom_info_contents, null);
|
||||
render(marker, infoContent);
|
||||
return infoContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改背景
|
||||
*
|
||||
* @param marker
|
||||
*/
|
||||
@Override
|
||||
public View getInfoWindow(Marker marker) {
|
||||
View infoWindow = getLayoutInflater().inflate(
|
||||
R.layout.custom_info_window, null);
|
||||
render(marker, infoWindow);
|
||||
return infoWindow;
|
||||
}
|
||||
|
||||
/**
|
||||
* 渲染
|
||||
*
|
||||
* @param marker
|
||||
* @param view
|
||||
*/
|
||||
private void render(Marker marker, View view) {
|
||||
((ImageView) view.findViewById(R.id.badge))
|
||||
.setImageResource(R.mipmap.ic_yuan);
|
||||
|
||||
//修改InfoWindow标题内容样式
|
||||
String title = marker.getTitle();
|
||||
TextView titleUi = ((TextView) view.findViewById(R.id.title));
|
||||
if (title != null) {
|
||||
SpannableString titleText = new SpannableString(title);
|
||||
titleText.setSpan(new ForegroundColorSpan(Color.RED), 0,
|
||||
titleText.length(), 0);
|
||||
titleUi.setTextSize(15);
|
||||
titleUi.setText(titleText);
|
||||
|
||||
} else {
|
||||
titleUi.setText("");
|
||||
}
|
||||
//修改InfoWindow片段内容样式
|
||||
String snippet = marker.getSnippet();
|
||||
TextView snippetUi = ((TextView) view.findViewById(R.id.snippet));
|
||||
if (snippet != null) {
|
||||
SpannableString snippetText = new SpannableString(snippet);
|
||||
snippetText.setSpan(new ForegroundColorSpan(Color.GREEN), 0,
|
||||
snippetText.length(), 0);
|
||||
snippetUi.setTextSize(20);
|
||||
snippetUi.setText(snippetText);
|
||||
} else {
|
||||
snippetUi.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* InfoWindow点击事件
|
||||
*
|
||||
* @param marker
|
||||
*/
|
||||
@Override
|
||||
public void onInfoWindowClick(Marker marker) {
|
||||
showMsg("弹窗内容:标题:" + marker.getTitle() + "\n内容:" + marker.getSnippet());
|
||||
}
|
||||
|
||||
}
|
||||
841
app/src/main/java/com/example/mangowalking/RouteActivity.java
Normal file
@@ -0,0 +1,841 @@
|
||||
package com.example.mangowalking;
|
||||
|
||||
import static com.example.mangowalking.utils.MapUtil.convertToLatLng;
|
||||
import static com.example.mangowalking.utils.MapUtil.convertToLatLonPoint;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
|
||||
import android.bluetooth.BluetoothAdapter;
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothGattCallback;
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.bluetooth.BluetoothGattDescriptor;
|
||||
import android.bluetooth.BluetoothGattService;
|
||||
import android.bluetooth.BluetoothManager;
|
||||
import android.bluetooth.BluetoothProfile;
|
||||
import android.bluetooth.le.BluetoothLeScanner;
|
||||
import android.bluetooth.le.ScanCallback;
|
||||
import android.bluetooth.le.ScanFilter;
|
||||
import android.bluetooth.le.ScanResult;
|
||||
import android.bluetooth.le.ScanSettings;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
import android.os.ParcelUuid;
|
||||
import android.util.Log;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.Spinner;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.activity.result.ActivityResultLauncher;
|
||||
import androidx.activity.result.contract.ActivityResultContracts;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
|
||||
import com.amap.api.location.AMapLocation;
|
||||
import com.amap.api.location.AMapLocationClient;
|
||||
import com.amap.api.location.AMapLocationClientOption;
|
||||
import com.amap.api.location.AMapLocationListener;
|
||||
import com.amap.api.maps.AMap;
|
||||
import com.amap.api.maps.LocationSource;
|
||||
import com.amap.api.maps.UiSettings;
|
||||
import com.amap.api.maps.model.BitmapDescriptorFactory;
|
||||
import com.amap.api.maps.model.LatLng;
|
||||
import com.amap.api.maps.model.MarkerOptions;
|
||||
import com.amap.api.maps.model.MyLocationStyle;
|
||||
import com.amap.api.services.busline.BusLineItem;
|
||||
import com.amap.api.services.core.AMapException;
|
||||
import com.amap.api.services.core.LatLonPoint;
|
||||
import com.amap.api.services.geocoder.GeocodeAddress;
|
||||
import com.amap.api.services.geocoder.GeocodeQuery;
|
||||
import com.amap.api.services.geocoder.GeocodeResult;
|
||||
import com.amap.api.services.geocoder.GeocodeSearch;
|
||||
import com.amap.api.services.geocoder.RegeocodeResult;
|
||||
import com.amap.api.services.route.BusPath;
|
||||
import com.amap.api.services.route.BusRouteResult;
|
||||
import com.amap.api.services.route.BusStep;
|
||||
import com.amap.api.services.route.DriveRouteResult;
|
||||
import com.amap.api.services.route.RideRouteResult;
|
||||
import com.amap.api.services.route.RouteBusLineItem;
|
||||
import com.amap.api.services.route.RouteSearch;
|
||||
import com.amap.api.services.route.WalkPath;
|
||||
import com.amap.api.services.route.WalkRouteResult;
|
||||
import com.amap.api.services.route.WalkStep;
|
||||
import com.example.mangowalking.databinding.ActivityRouteBinding;
|
||||
import com.example.mangowalking.overlay.BusRouteOverlay;
|
||||
import com.example.mangowalking.overlay.WalkRouteOverlay;
|
||||
import com.example.mangowalking.utils.MapUtil;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class RouteActivity extends AppCompatActivity implements
|
||||
AMapLocationListener, LocationSource, AMap.OnMapClickListener, RouteSearch.OnRouteSearchListener, GeocodeSearch.OnGeocodeSearchListener, View.OnKeyListener {
|
||||
|
||||
|
||||
private static final String TAG = "RouteActivity";
|
||||
private ActivityRouteBinding binding;
|
||||
//地图控制器
|
||||
private AMap aMap = null;
|
||||
//声明AMapLocationClient类对象
|
||||
public AMapLocationClient mLocationClient = null;
|
||||
//声明AMapLocationClientOption对象
|
||||
public AMapLocationClientOption mLocationOption = null;
|
||||
//位置更改监听
|
||||
private LocationSource.OnLocationChangedListener mListener;
|
||||
//定义一个UiSettings对象
|
||||
private UiSettings mUiSettings;
|
||||
//定位样式
|
||||
private MyLocationStyle myLocationStyle = new MyLocationStyle();
|
||||
|
||||
//起点
|
||||
private LatLonPoint mStartPoint;
|
||||
//终点
|
||||
private LatLonPoint mEndPoint;
|
||||
//路线搜索对象
|
||||
private RouteSearch routeSearch;
|
||||
|
||||
//出行方式数组
|
||||
private static final String[] travelModeArray = {"步行出行", "公交出行"};
|
||||
|
||||
//出行方式值
|
||||
private static int TRAVEL_MODE = 0;
|
||||
|
||||
//数组适配器
|
||||
private ArrayAdapter<String> arrayAdapter;
|
||||
//地理编码搜索
|
||||
private GeocodeSearch geocodeSearch;
|
||||
//解析成功标识码
|
||||
private static final int PARSE_SUCCESS_CODE = 1000;
|
||||
//定位地址
|
||||
private String locationAddress;
|
||||
//城市
|
||||
private String city;
|
||||
//起点地址转坐标标识 1
|
||||
private int tag = -1;
|
||||
|
||||
//路线规划详情
|
||||
private RelativeLayout bottomLayout;
|
||||
//花费时间
|
||||
private TextView tvTime;
|
||||
|
||||
//添加关于蓝牙的变量
|
||||
private BluetoothLeScanner scanner;
|
||||
|
||||
private BluetoothDevice device;
|
||||
|
||||
private BluetoothGatt bluetoothGatt;
|
||||
|
||||
private boolean isBluetoothConnected = false;
|
||||
|
||||
private String SERVICE_UUID = "0000FFE0-0000-1000-8000-00805F9B34FB";
|
||||
private String READ_UUID = "0000FFE0-0000-1000-8000-00805F9B34FB";
|
||||
|
||||
private String READ_DEDSCRIPTION_UUID = "00002902-0000-1000-8000-00805f9b34fb";
|
||||
|
||||
private BluetoothGattCharacteristic writeCharacteristic;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
EdgeToEdge.enable(this);
|
||||
binding = ActivityRouteBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||
return insets;
|
||||
});
|
||||
//添加蓝牙开启 蓝牙部分是成功开启了
|
||||
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
|
||||
Toast.makeText(RouteActivity.this, "没有蓝牙", Toast.LENGTH_SHORT).show();
|
||||
} else {
|
||||
Toast.makeText(RouteActivity.this, "该设备支持蓝牙", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
final BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
|
||||
BluetoothAdapter bluetoothAdapter = bluetoothManager.getAdapter();
|
||||
|
||||
ActivityResultLauncher<Intent> launcher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), result -> {
|
||||
if (result.getResultCode() == RESULT_OK) {
|
||||
//处理返回结果
|
||||
Toast.makeText(RouteActivity.this, "已成功开启蓝牙", Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
@SuppressLint("MissingPermission")
|
||||
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); //创建一个蓝牙启动的意图
|
||||
launcher.launch(enableBtIntent);//使用launcer启动这个意图就可以了。
|
||||
//此处可行
|
||||
//初始化定位
|
||||
initLocation();
|
||||
//初始化地图
|
||||
initMap(savedInstanceState);
|
||||
//启动定位
|
||||
mLocationClient.startLocation();
|
||||
initRoute();
|
||||
//初始化出行方式
|
||||
initTravelMode();
|
||||
|
||||
// 新加入的
|
||||
scanner = bluetoothAdapter.getBluetoothLeScanner();
|
||||
//不进行权限验证
|
||||
ScanCallback callback = new ScanCallback() {
|
||||
@Override
|
||||
public void onScanResult(int callbackType, ScanResult result) {
|
||||
device = result.getDevice();//得到设备
|
||||
// Log.e(TAG, "发现设备" + device.getName());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScanFailed(int errorCode) {
|
||||
super.onScanFailed(errorCode);
|
||||
Log.e(TAG, "搜索错误" + errorCode);
|
||||
}
|
||||
};
|
||||
ScanFilter sn = new ScanFilter.Builder().setDeviceName("蓝牙设备的名称").setServiceUuid(ParcelUuid.fromString("0000FFE0-0000-1000-8000-00805F9B34FB")).build();
|
||||
List<ScanFilter> scanFilters = new ArrayList<>();
|
||||
scanFilters.add(sn);
|
||||
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_SCAN) != PackageManager.PERMISSION_GRANTED) {
|
||||
// TODO: Consider calling
|
||||
// ActivityCompat#requestPermissions
|
||||
return;
|
||||
}
|
||||
scanner.startScan(scanFilters, new ScanSettings.Builder().build(), callback);
|
||||
bluetoothGatt = device.connectGatt(this, false, gattCallback);
|
||||
}
|
||||
|
||||
BluetoothGattCallback gattCallback = new BluetoothGattCallback() {
|
||||
//GATT的链接状态回调
|
||||
@Override
|
||||
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
|
||||
super.onConnectionStateChange(gatt, status, newState);
|
||||
if (newState == BluetoothProfile.STATE_CONNECTED) {
|
||||
if (ActivityCompat.checkSelfPermission(RouteActivity.this, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
|
||||
return;
|
||||
}
|
||||
gatt.discoverServices();
|
||||
Log.v(TAG, "连接成功");
|
||||
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
|
||||
Log.e(TAG, "连接断开");
|
||||
} else if (newState == BluetoothProfile.STATE_CONNECTING) {
|
||||
//TODO 在实际过程中,该方法并没有调用
|
||||
Log.e(TAG, "连接中....");
|
||||
}
|
||||
}
|
||||
|
||||
//获取GATT服务发现后的回调
|
||||
@Override
|
||||
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
|
||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||
Log.e(TAG, "GATT_SUCCESS"); //服务发现
|
||||
for (BluetoothGattService bluetoothGattService : gatt.getServices()) {
|
||||
Log.e(TAG, "Service_UUID" + bluetoothGattService.getUuid()); // 我们可以遍历到该蓝牙设备的全部Service对象。然后通过比较Service的UUID,我们可以区分该服务是属于什么业务的
|
||||
if (SERVICE_UUID.equals(bluetoothGattService.getUuid().toString())) {
|
||||
|
||||
for (BluetoothGattCharacteristic characteristic : bluetoothGattService.getCharacteristics()) {
|
||||
prepareBroadcastDataNotify(gatt, characteristic); //给满足条件的属性配置上消息通知
|
||||
}
|
||||
return;//结束循环操作
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "onServicesDiscovered received: " + status);
|
||||
}
|
||||
}
|
||||
|
||||
//蓝牙设备发送消息后的自动监听
|
||||
@Override
|
||||
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
|
||||
// readUUID 是我要链接的蓝牙设备的消息读UUID值,跟通知的特性的UUID比较。这样可以避免其他消息的污染。
|
||||
if (READ_UUID.equals(characteristic.getUuid().toString())) {
|
||||
try {
|
||||
String chara = new String(characteristic.getValue(), "UTF-8");
|
||||
Log.e(TAG, "消息内容:" + chara);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@SuppressLint("MissingPermission")
|
||||
private void prepareBroadcastDataNotify(BluetoothGatt mBluetoothGatt, BluetoothGattCharacteristic characteristic) {
|
||||
Log.e(TAG, "CharacteristicUUID:" + characteristic.getUuid().toString());
|
||||
int charaProp = characteristic.getProperties();
|
||||
//判断属性是否支持消息通知
|
||||
if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
|
||||
BluetoothGattDescriptor descriptor =
|
||||
characteristic.getDescriptor(UUID.fromString(READ_DEDSCRIPTION_UUID));
|
||||
if (descriptor != null) {
|
||||
//注册消息通知
|
||||
mBluetoothGatt.setCharacteristicNotification(characteristic, true);
|
||||
descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
|
||||
mBluetoothGatt.writeDescriptor(descriptor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
|
||||
if (status == BluetoothGatt.GATT_SUCCESS) {
|
||||
BluetoothGattService service = gatt.getService(UUID.fromString(SERVICE_UUID));
|
||||
if (service != null) {
|
||||
// 假设写特征的 UUID 就是 READ_UUID(或者你需要再定义一个 WRITE_UUID)
|
||||
writeCharacteristic = service.getCharacteristic(UUID.fromString(READ_UUID));
|
||||
// 如果该特征需要先 enableNotification,也可在这里设置:
|
||||
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
|
||||
return;
|
||||
}
|
||||
gatt.setCharacteristicNotification(writeCharacteristic, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过 BLE 将 poiList 中的每个坐标点逐条发送到从机。
|
||||
* 由于单包 MTU 默认为 20 字节,必要时需要分包。
|
||||
*/
|
||||
private void sendPoiList(List<LatLng> poiList) {
|
||||
if (writeCharacteristic == null || bluetoothGatt == null) {
|
||||
showMsg("蓝牙特征或连接未准备好");
|
||||
return;
|
||||
}
|
||||
|
||||
for (LatLng p : poiList) {
|
||||
// 1) 将坐标格式化为字符串,比如:"31.2304,121.4737\n"
|
||||
String str = p.latitude + "," + p.longitude + "\n";
|
||||
byte[] data = str.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
// 2) 如果 data.length > MTU,需要分包;这里简单示例不分包
|
||||
writeCharacteristic.setValue(data);
|
||||
|
||||
// 3) 发写命令,异步执行
|
||||
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
|
||||
return;
|
||||
}
|
||||
boolean success = bluetoothGatt.writeCharacteristic(writeCharacteristic);
|
||||
if (!success) {
|
||||
Log.e(TAG, "写入特征失败:" + str);
|
||||
}
|
||||
|
||||
// 4) 为避免短时间内连续写多包导致丢包,可在这里短暂停一下(示例用 Handler)
|
||||
try {
|
||||
Thread.sleep(50);
|
||||
} catch (InterruptedException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化出行方式
|
||||
*/
|
||||
private void initTravelMode() {
|
||||
Spinner spinner = findViewById(R.id.spinner);
|
||||
|
||||
//将可选内容与ArrayAdapter连接起来
|
||||
arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_spinner_item, travelModeArray);
|
||||
//设置下拉列表的风格
|
||||
arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
|
||||
//将adapter 添加到spinner中
|
||||
spinner.setAdapter(arrayAdapter);
|
||||
//添加事件Spinner事件监听
|
||||
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
|
||||
@Override
|
||||
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
|
||||
TRAVEL_MODE = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onNothingSelected(AdapterView<?> parent) {
|
||||
}
|
||||
});
|
||||
//键盘按键监听
|
||||
//起点 键盘按键监听
|
||||
binding.etStartAddress.setOnKeyListener(this);
|
||||
//终点 键盘按键监听
|
||||
binding.etEndAddress.setOnKeyListener(this);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化路线
|
||||
*/
|
||||
private void initRoute() {
|
||||
try {
|
||||
routeSearch = new RouteSearch(this);
|
||||
} catch (AMapException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
routeSearch.setRouteSearchListener(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化定位
|
||||
*/
|
||||
private void initLocation() {
|
||||
//初始化定位
|
||||
try {
|
||||
mLocationClient = new AMapLocationClient(getApplicationContext());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if (mLocationClient != null) {
|
||||
mLocationClient.setLocationListener(this);
|
||||
mLocationOption = new AMapLocationClientOption();
|
||||
mLocationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
|
||||
mLocationOption.setOnceLocationLatest(true);
|
||||
mLocationOption.setNeedAddress(true);
|
||||
mLocationOption.setHttpTimeOut(20000);
|
||||
mLocationOption.setLocationCacheEnable(false);
|
||||
mLocationClient.setLocationOption(mLocationOption);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化地图
|
||||
*
|
||||
* @param savedInstanceState
|
||||
*/
|
||||
private void initMap(Bundle savedInstanceState) {
|
||||
binding.mapView.onCreate(savedInstanceState);
|
||||
//初始化地图控制器对象
|
||||
aMap = binding.mapView.getMap();
|
||||
//设置最小缩放等级为12 ,缩放级别范围为[3, 20]
|
||||
aMap.setMinZoomLevel(12);
|
||||
//开启室内地图
|
||||
aMap.showIndoorMap(true);
|
||||
//实例化UiSettings类对象
|
||||
mUiSettings = aMap.getUiSettings();
|
||||
//隐藏缩放按钮 默认显示
|
||||
mUiSettings.setZoomControlsEnabled(false);
|
||||
//显示比例尺 默认不显示
|
||||
mUiSettings.setScaleControlsEnabled(true);
|
||||
// 自定义定位蓝点图标
|
||||
myLocationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.drawable.gps_point));
|
||||
//设置定位蓝点的Style
|
||||
aMap.setMyLocationStyle(myLocationStyle);
|
||||
// 设置定位监听
|
||||
aMap.setLocationSource(this);
|
||||
// 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false
|
||||
aMap.setMyLocationEnabled(true);
|
||||
//地图点击监听
|
||||
aMap.setOnMapClickListener(this);
|
||||
//构造 GeocodeSearch 对象
|
||||
try {
|
||||
geocodeSearch = new GeocodeSearch(this);
|
||||
} catch (AMapException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
//设置监听
|
||||
geocodeSearch.setOnGeocodeSearchListener(this);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLocationChanged(AMapLocation aMapLocation) {
|
||||
if (aMapLocation != null) {
|
||||
if (aMapLocation.getErrorCode() == 0) {
|
||||
//地址
|
||||
String address = aMapLocation.getAddress();
|
||||
//获取纬度
|
||||
double latitude = aMapLocation.getLatitude();
|
||||
//获取经度
|
||||
double longitude = aMapLocation.getLongitude();
|
||||
//设置当前所在地
|
||||
//地址
|
||||
locationAddress = aMapLocation.getAddress();
|
||||
//设置当前所在地
|
||||
binding.etStartAddress.setText(locationAddress);
|
||||
//binding.etStartAddress.setEnabled(false);//禁用输入
|
||||
//城市赋值
|
||||
city = aMapLocation.getCity();
|
||||
Log.d(TAG, address);
|
||||
//设置起点
|
||||
mStartPoint = convertToLatLonPoint(new LatLng(latitude, longitude));
|
||||
//停止定位后,本地定位服务并不会被销毁
|
||||
mLocationClient.stopLocation();
|
||||
|
||||
//显示地图定位结果
|
||||
if (mListener != null) {
|
||||
// 显示系统图标
|
||||
mListener.onLocationChanged(aMapLocation);
|
||||
}
|
||||
|
||||
} else {
|
||||
//定位失败时,可通过ErrCode(错误码)信息来确定失败的原因,errInfo是错误信息,详见错误码表。
|
||||
Log.e("AmapError", "location Error, ErrCode:"
|
||||
+ aMapLocation.getErrorCode() + ", errInfo:"
|
||||
+ aMapLocation.getErrorInfo());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开始路线搜索
|
||||
*/
|
||||
private void startRouteSearch() {
|
||||
//在地图上添加起点Marker
|
||||
aMap.addMarker(new MarkerOptions()
|
||||
.position(convertToLatLng(mStartPoint))
|
||||
.icon(BitmapDescriptorFactory.fromResource(R.drawable.start)));
|
||||
//在地图上添加终点Marker
|
||||
aMap.addMarker(new MarkerOptions()
|
||||
.position(convertToLatLng(mEndPoint))
|
||||
.icon(BitmapDescriptorFactory.fromResource(R.drawable.end)));
|
||||
|
||||
//搜索路线 构建路径的起终点
|
||||
final RouteSearch.FromAndTo fromAndTo = new RouteSearch.FromAndTo(
|
||||
mStartPoint, mEndPoint);
|
||||
//出行方式判断
|
||||
switch (TRAVEL_MODE) {
|
||||
case 0://步行
|
||||
//构建步行路线搜索对象
|
||||
RouteSearch.WalkRouteQuery query = new RouteSearch.WalkRouteQuery(fromAndTo, RouteSearch.WalkDefault);
|
||||
// 异步路径规划步行模式查询
|
||||
routeSearch.calculateWalkRouteAsyn(query);
|
||||
break;
|
||||
case 1://骑行
|
||||
//构建驾车路线搜索对象 第三个参数表示公交查询城市区号,第四个参数表示是否计算夜班车,0表示不计算,1表示计算
|
||||
RouteSearch.BusRouteQuery busQuery = new RouteSearch.BusRouteQuery(fromAndTo, RouteSearch.BusLeaseWalk, city, 1);
|
||||
//公交规划路径计算
|
||||
routeSearch.calculateBusRouteAsyn(busQuery);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void activate(LocationSource.OnLocationChangedListener onLocationChangedListener) {
|
||||
mListener = onLocationChangedListener;
|
||||
if (mLocationClient == null) {
|
||||
mLocationClient.startLocation();//启动定位
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deactivate() {
|
||||
mListener = null;
|
||||
if (mLocationClient != null) {
|
||||
mLocationClient.stopLocation();
|
||||
mLocationClient.onDestroy();
|
||||
}
|
||||
mLocationClient = null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
binding.mapView.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
binding.mapView.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
binding.mapView.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
//销毁定位客户端,同时销毁本地定位服务。
|
||||
if (mLocationClient != null) {
|
||||
mLocationClient.onDestroy();
|
||||
}
|
||||
binding.mapView.onDestroy();
|
||||
|
||||
if (bluetoothGatt != null) {
|
||||
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.BLUETOOTH_CONNECT) != PackageManager.PERMISSION_GRANTED) {
|
||||
return;
|
||||
}
|
||||
bluetoothGatt.close();
|
||||
bluetoothGatt.disconnect();
|
||||
bluetoothGatt = null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void showMsg(CharSequence llw) {
|
||||
Toast.makeText(this, llw, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
/**
|
||||
* 点击地图
|
||||
*/
|
||||
@Override
|
||||
public void onMapClick(LatLng latLng) {
|
||||
//终点
|
||||
mEndPoint = convertToLatLonPoint(latLng);
|
||||
//开始路线搜索
|
||||
startRouteSearch();
|
||||
}
|
||||
|
||||
/**
|
||||
* 公交规划路径结果
|
||||
*
|
||||
* @param busRouteResult 结果
|
||||
* @param code 结果码
|
||||
*/
|
||||
@Override
|
||||
public void onBusRouteSearched(BusRouteResult busRouteResult, int code) {
|
||||
aMap.clear();// 清理地图上的所有覆盖物
|
||||
if (code != AMapException.CODE_AMAP_SUCCESS) {
|
||||
showMsg("错误码;" + code);
|
||||
return;
|
||||
}
|
||||
if (busRouteResult == null || busRouteResult.getPaths() == null) {
|
||||
showMsg("对不起,没有搜索到相关数据!");
|
||||
return;
|
||||
}
|
||||
if (busRouteResult.getPaths().isEmpty()) {
|
||||
showMsg("对不起,没有搜索到相关数据!");
|
||||
return;
|
||||
}
|
||||
final BusPath busPath = busRouteResult.getPaths().get(0);
|
||||
if (busPath == null) {
|
||||
return;
|
||||
}
|
||||
// 绘制路线
|
||||
BusRouteOverlay busRouteOverlay = new BusRouteOverlay(
|
||||
this, aMap, busPath,
|
||||
busRouteResult.getStartPos(),
|
||||
busRouteResult.getTargetPos());
|
||||
busRouteOverlay.removeFromMap();
|
||||
busRouteOverlay.addToMap();
|
||||
busRouteOverlay.zoomToSpan();
|
||||
|
||||
int dis = (int) busPath.getDistance();
|
||||
int dur = (int) busPath.getDuration();
|
||||
String des = MapUtil.getFriendlyTime(dur) + "(" + MapUtil.getFriendlyLength(dis) + ")";
|
||||
Log.d(TAG, des);
|
||||
//显示公交花费时间
|
||||
//显示公交花费时间
|
||||
binding.tvTime.setText(des);
|
||||
binding.layBottom.setVisibility(View.VISIBLE);
|
||||
//跳转到路线详情页面
|
||||
binding.tvDetail.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(RouteActivity.this,
|
||||
RouteDetailActivity.class);
|
||||
intent.putExtra("type",1);
|
||||
intent.putExtra("path", busPath);
|
||||
startActivity(intent);
|
||||
});
|
||||
List<LatLng> allPoiPoints = new ArrayList<>();
|
||||
|
||||
List<BusStep> steps = busPath.getSteps();
|
||||
for (BusStep step : steps) {
|
||||
|
||||
// 🟢 步行部分
|
||||
if (step.getWalk() != null && step.getWalk().getSteps() != null) {
|
||||
List<WalkStep> walkSteps = step.getWalk().getSteps();
|
||||
for (WalkStep walkStep : walkSteps) {
|
||||
List<LatLonPoint> polyline = walkStep.getPolyline();
|
||||
for (LatLonPoint point : polyline) {
|
||||
allPoiPoints.add(new LatLng(point.getLatitude(), point.getLongitude()));
|
||||
Log.d("Walk:",point.getLatitude() + "," + point.getLongitude());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 🟠 公交部分
|
||||
if (step.getBusLines() != null && !step.getBusLines().isEmpty()) {
|
||||
BusLineItem busLine = step.getBusLines().get(0); // 取当前段第一条公交车
|
||||
List<LatLonPoint> busPoints = ((RouteBusLineItem) busLine).getPolyline(); // 🚍 公交线路坐标
|
||||
for (LatLonPoint point : busPoints) {
|
||||
allPoiPoints.add(new LatLng(point.getLatitude(), point.getLongitude()));
|
||||
Log.d("Bus:",point.getLatitude() + "," + point.getLongitude());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// // 🧪 测试打印
|
||||
// for (LatLng p : poiList) {
|
||||
// Log.d("POI_POINT", p.latitude + "," + p.longitude);
|
||||
// }
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onDriveRouteSearched(DriveRouteResult driveRouteResult, int i) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 步行规划路径结果
|
||||
*
|
||||
* @param walkRouteResult 结果
|
||||
* @param code 结果码
|
||||
*/
|
||||
@Override
|
||||
public void onWalkRouteSearched(WalkRouteResult walkRouteResult, int code) {
|
||||
aMap.clear();// 清理地图上的所有覆盖物
|
||||
if (code != AMapException.CODE_AMAP_SUCCESS) {
|
||||
showMsg("错误码;" + code);
|
||||
return;
|
||||
}
|
||||
if (walkRouteResult == null || walkRouteResult.getPaths() == null) {
|
||||
showMsg("对不起,没有搜索到相关数据!");
|
||||
return;
|
||||
}
|
||||
if (walkRouteResult.getPaths().isEmpty()) {
|
||||
showMsg("对不起,没有搜索到相关数据!");
|
||||
return;
|
||||
}
|
||||
final WalkPath walkPath = walkRouteResult.getPaths().get(0);
|
||||
if (walkPath == null) {
|
||||
return;
|
||||
}
|
||||
//绘制路线
|
||||
WalkRouteOverlay walkRouteOverlay = new WalkRouteOverlay(
|
||||
this, aMap, walkPath,
|
||||
walkRouteResult.getStartPos(),
|
||||
walkRouteResult.getTargetPos());
|
||||
walkRouteOverlay.removeFromMap();
|
||||
walkRouteOverlay.addToMap();
|
||||
walkRouteOverlay.zoomToSpan();
|
||||
|
||||
int dis = (int) walkPath.getDistance();
|
||||
int dur = (int) walkPath.getDuration();
|
||||
String des = MapUtil.getFriendlyTime(dur) + "(" + MapUtil.getFriendlyLength(dis) + ")";
|
||||
Log.d(TAG, des);
|
||||
//显示步行花费时间
|
||||
binding.tvTime.setText(des);
|
||||
binding.layBottom.setVisibility(View.VISIBLE);
|
||||
//跳转到路线详情页面
|
||||
binding.tvDetail.setOnClickListener(v -> {
|
||||
Intent intent = new Intent(RouteActivity.this,
|
||||
RouteDetailActivity.class);
|
||||
intent.putExtra("type",0);
|
||||
intent.putExtra("path", walkPath);
|
||||
startActivity(intent);
|
||||
});
|
||||
List<LatLng> poiList = new ArrayList<>();
|
||||
|
||||
List<WalkStep> steps = walkPath.getSteps();
|
||||
for (WalkStep step : steps) {
|
||||
List<LatLonPoint> polyline = step.getPolyline();
|
||||
for (LatLonPoint point : polyline) {
|
||||
LatLng latLng = new LatLng(point.getLatitude(), point.getLongitude());
|
||||
poiList.add(latLng);
|
||||
}
|
||||
}
|
||||
|
||||
// 🧪 测试打印
|
||||
for (LatLng p : poiList) {
|
||||
Log.d("POI_POINT", p.latitude + "," + p.longitude);
|
||||
}
|
||||
sendPoiList(poiList);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onRideRouteSearched(RideRouteResult rideRouteResult, int i) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRegeocodeSearched(RegeocodeResult regeocodeResult, int i) {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 地址转坐标
|
||||
*
|
||||
* @param geocodeResult
|
||||
* @param rCode
|
||||
*/
|
||||
@Override
|
||||
public void onGeocodeSearched(GeocodeResult geocodeResult, int rCode) {
|
||||
if (rCode != PARSE_SUCCESS_CODE) {
|
||||
showMsg("获取坐标失败,错误码:" + rCode);
|
||||
return;
|
||||
}
|
||||
List<GeocodeAddress> geocodeAddressList = geocodeResult.getGeocodeAddressList();
|
||||
if (geocodeAddressList != null && !geocodeAddressList.isEmpty()) {
|
||||
//判断是不是起点的搜索
|
||||
if (tag == 1) {
|
||||
//起点
|
||||
mStartPoint = geocodeAddressList.get(0).getLatLonPoint();
|
||||
} else {
|
||||
//终点
|
||||
mEndPoint = geocodeAddressList.get(0).getLatLonPoint();
|
||||
}
|
||||
if (mStartPoint != null && mEndPoint != null) {
|
||||
//开始路线搜索
|
||||
startRouteSearch();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_UP) {
|
||||
//获取输入框的值 出发地(起点)
|
||||
String startAddress = binding.etStartAddress.getText().toString().trim();
|
||||
//获取输入框的值 目的地(终点)
|
||||
String endAddress = binding.etEndAddress.getText().toString().trim();
|
||||
|
||||
//判断出发地是否有值 不管这个值是定位还是手动输入
|
||||
if (startAddress.isEmpty()) {
|
||||
showMsg("请输入当前的出发地");
|
||||
return false;
|
||||
}
|
||||
//判断目的地是否有值
|
||||
if (endAddress.isEmpty()) {
|
||||
showMsg("请输入要前往的目的地");
|
||||
return false;
|
||||
}
|
||||
|
||||
//当出发地输入框有值的时候,判断这个值是否是定位的地址,是则说明你没有更改过,则不需要进行地址转坐标,不是则需要转换。
|
||||
if (!locationAddress.equals(startAddress)) {
|
||||
tag = 1;
|
||||
GeocodeQuery startQuery = new GeocodeQuery(startAddress, city);
|
||||
geocodeSearch.getFromLocationNameAsyn(startQuery);
|
||||
} else {
|
||||
tag = -1;
|
||||
}
|
||||
|
||||
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
//隐藏软键盘
|
||||
imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0);
|
||||
|
||||
//通过输入的目的地转为经纬度,然后进行地图上添加标点,最后计算出行路线规划
|
||||
|
||||
// name表示地址,第二个参数表示查询城市,中文或者中文全拼,citycode、adcode
|
||||
GeocodeQuery endQuery = new GeocodeQuery(endAddress, city);
|
||||
geocodeSearch.getFromLocationNameAsyn(endQuery);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
package com.example.mangowalking;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.activity.EdgeToEdge;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.graphics.Insets;
|
||||
import androidx.core.view.ViewCompat;
|
||||
import androidx.core.view.WindowInsetsCompat;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.amap.api.services.route.BusPath;
|
||||
import com.amap.api.services.route.BusStep;
|
||||
import com.amap.api.services.route.WalkPath;
|
||||
import com.example.mangowalking.adapter.BusSegmentListAdapter;
|
||||
import com.example.mangowalking.adapter.WalkSegmentListAdapter;
|
||||
import com.example.mangowalking.databinding.ActivityRouteDetailBinding;
|
||||
import com.example.mangowalking.utils.MapUtil;
|
||||
import com.example.mangowalking.utils.SchemeBusStep;
|
||||
|
||||
import java.text.BreakIterator;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class RouteDetailActivity extends AppCompatActivity {
|
||||
|
||||
private ActivityRouteDetailBinding binding;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
EdgeToEdge.enable(this);
|
||||
binding = ActivityRouteDetailBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
|
||||
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
|
||||
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
|
||||
return insets;
|
||||
});
|
||||
initView();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 初始化视图
|
||||
*/
|
||||
private void initView() {
|
||||
binding.toolbar.setNavigationOnClickListener(v -> finish());
|
||||
Intent intent = getIntent();
|
||||
if (intent == null) {
|
||||
return;
|
||||
}
|
||||
switch (intent.getIntExtra("type", 0)) {
|
||||
case 0://步行
|
||||
walkDetail(intent);
|
||||
break;
|
||||
case 1://
|
||||
busDetail(intent);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 步行详情
|
||||
* @param intent
|
||||
*/
|
||||
private void walkDetail(Intent intent) {
|
||||
binding.toolbar.setTitle("步行路线规划");
|
||||
WalkPath walkPath = intent.getParcelableExtra("path");
|
||||
String dur = MapUtil.getFriendlyTime((int) walkPath.getDuration());
|
||||
String dis = MapUtil.getFriendlyLength((int) walkPath.getDistance());
|
||||
binding.tvTime.setText(dur + "(" + dis + ")");
|
||||
binding.rvRouteDetail.setLayoutManager(new LinearLayoutManager(this));
|
||||
binding.rvRouteDetail.setAdapter(new WalkSegmentListAdapter(walkPath.getSteps()));
|
||||
}
|
||||
|
||||
private void busDetail(Intent intent) {
|
||||
binding.toolbar.setTitle("公交路线规划");
|
||||
|
||||
BusPath busPath = intent.getParcelableExtra("path");
|
||||
if (busPath == null) {
|
||||
Log.e("RouteDetail", "busPath is null!");
|
||||
return;
|
||||
}
|
||||
|
||||
String dur = MapUtil.getFriendlyTime((int) busPath.getDuration());
|
||||
String dis = MapUtil.getFriendlyLength((int) busPath.getDistance());
|
||||
binding.tvTime.setText(dur + "(" + dis + ")");
|
||||
|
||||
List<SchemeBusStep> stepList = getBusSteps(busPath.getSteps());
|
||||
Log.d("RouteDetail", "Steps count: " + stepList.size());
|
||||
|
||||
binding.rvRouteDetail.setLayoutManager(new LinearLayoutManager(this));
|
||||
binding.rvRouteDetail.setAdapter(new BusSegmentListAdapter(R.layout.item_segment, stepList));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 公交方案数据组装
|
||||
* @param list
|
||||
* @return
|
||||
*/
|
||||
private List<SchemeBusStep> getBusSteps(List<BusStep> list) {
|
||||
List<SchemeBusStep> busStepList = new ArrayList<>();
|
||||
SchemeBusStep start = new SchemeBusStep(null);
|
||||
start.setStart(true);
|
||||
busStepList.add(start);
|
||||
for (BusStep busStep : list) {
|
||||
if (busStep.getWalk() != null && busStep.getWalk().getDistance() > 0) {
|
||||
SchemeBusStep walk = new SchemeBusStep(busStep);
|
||||
walk.setWalk(true);
|
||||
busStepList.add(walk);
|
||||
}
|
||||
if (busStep.getBusLine() != null) {
|
||||
SchemeBusStep bus = new SchemeBusStep(busStep);
|
||||
bus.setBus(true);
|
||||
busStepList.add(bus);
|
||||
}
|
||||
if (busStep.getRailway() != null) {
|
||||
SchemeBusStep railway = new SchemeBusStep(busStep);
|
||||
railway.setRailway(true);
|
||||
busStepList.add(railway);
|
||||
}
|
||||
|
||||
if (busStep.getTaxi() != null) {
|
||||
SchemeBusStep taxi = new SchemeBusStep(busStep);
|
||||
taxi.setTaxi(true);
|
||||
busStepList.add(taxi);
|
||||
}
|
||||
}
|
||||
SchemeBusStep end = new SchemeBusStep(null);
|
||||
end.setEnd(true);
|
||||
busStepList.add(end);
|
||||
return busStepList;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
package com.example.mangowalking.adapter;
|
||||
|
||||
import static com.amap.api.maps.model.BitmapDescriptorFactory.getContext;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.amap.api.services.busline.BusStationItem;
|
||||
import com.amap.api.services.route.RailwayStationItem;
|
||||
import com.example.mangowalking.R;
|
||||
import com.example.mangowalking.databinding.ItemSegmentBinding;
|
||||
import com.example.mangowalking.utils.SchemeBusStep;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 公交段列表适配器
|
||||
*/
|
||||
public class BusSegmentListAdapter extends RecyclerView.Adapter<BusSegmentListAdapter.ViewHolder> {
|
||||
|
||||
private List<SchemeBusStep> mItemList;
|
||||
|
||||
public BusSegmentListAdapter(int item_segment, List<SchemeBusStep> data) {
|
||||
this.mItemList = data;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new ViewHolder(ItemSegmentBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
SchemeBusStep item = mItemList.get(position);
|
||||
if (position == 0) {
|
||||
holder.binding.busDirIcon.setImageResource(R.drawable.dir_start);
|
||||
holder.binding.busLineName.setText("出发");
|
||||
holder.binding.busDirIconUp.setVisibility(View.INVISIBLE);
|
||||
holder.binding.busDirIconDown.setVisibility(View.VISIBLE);
|
||||
holder.binding.busSegSplitLine.setVisibility(View.INVISIBLE);
|
||||
} else if (position == mItemList.size() - 1) {
|
||||
holder.binding.busDirIcon.setImageResource(R.drawable.dir_end);
|
||||
holder.binding.busLineName.setText("到达终点");
|
||||
holder.binding.busDirIconUp.setVisibility(View.VISIBLE);
|
||||
holder.binding.busDirIconDown.setVisibility(View.INVISIBLE);
|
||||
} else {
|
||||
if (item.isWalk() && item.getWalk() != null && item.getWalk().getDistance() > 0) {
|
||||
holder.binding.busDirIcon.setImageResource(R.drawable.dir13);
|
||||
holder.binding.busDirIconUp.setVisibility(View.VISIBLE);
|
||||
holder.binding.busDirIconDown.setVisibility(View.VISIBLE);
|
||||
holder.binding.busLineName.setText("步行"
|
||||
+ (int) item.getWalk().getDistance() + "米");
|
||||
holder.binding.busStationNum.setVisibility(View.GONE);
|
||||
holder.binding.busExpandImage.setVisibility(View.GONE);
|
||||
} else if (item.isBus() && item.getBusLines().size() > 0) {
|
||||
holder.binding.busDirIcon.setImageResource(R.drawable.dir14);
|
||||
holder.binding.busDirIconUp.setVisibility(View.VISIBLE);
|
||||
holder.binding.busDirIconDown.setVisibility(View.VISIBLE);
|
||||
holder.binding.busLineName.setText(item.getBusLines().get(0).getBusLineName());
|
||||
holder.binding.busStationNum.setVisibility(View.VISIBLE);
|
||||
holder.binding.busStationNum
|
||||
.setText((item.getBusLines().get(0).getPassStationNum() + 1) + "站");
|
||||
holder.binding.busExpandImage.setVisibility(View.VISIBLE);
|
||||
} else if (item.isRailway() && item.getRailway() != null) {
|
||||
holder.binding.busDirIcon.setImageResource(R.drawable.dir16);
|
||||
holder.binding.busDirIconUp.setVisibility(View.VISIBLE);
|
||||
holder.binding.busDirIconDown.setVisibility(View.VISIBLE);
|
||||
holder.binding.busLineName.setText(item.getRailway().getName());
|
||||
holder.binding.busStationNum.setVisibility(View.VISIBLE);
|
||||
holder.binding.busStationNum
|
||||
.setText((item.getRailway().getViastops().size() + 1) + "站");
|
||||
holder.binding.busExpandImage.setVisibility(View.VISIBLE);
|
||||
} else if (item.isTaxi() && item.getTaxi() != null) {
|
||||
holder.binding.busDirIcon.setImageResource(R.drawable.dir14);
|
||||
holder.binding.busDirIconUp.setVisibility(View.VISIBLE);
|
||||
holder.binding.busDirIconDown.setVisibility(View.VISIBLE);
|
||||
holder.binding.busLineName.setText("打车到终点");
|
||||
holder.binding.busStationNum.setVisibility(View.GONE);
|
||||
holder.binding.busExpandImage.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
holder.binding.busItem.setOnClickListener(v -> {
|
||||
if (item.isBus()) {//公交
|
||||
if (!item.isArrowExpend()) {
|
||||
item.setArrowExpend(true);
|
||||
holder.binding.busExpandImage.setImageResource(R.drawable.up);
|
||||
addBusStation(item.getBusLine().getDepartureBusStation(), holder.binding.expandContent);
|
||||
for (BusStationItem station : item.getBusLine()
|
||||
.getPassStations()) {
|
||||
addBusStation(station, holder.binding.expandContent);
|
||||
}
|
||||
addBusStation(item.getBusLine().getArrivalBusStation(), holder.binding.expandContent);
|
||||
|
||||
} else {
|
||||
item.setArrowExpend(false);
|
||||
holder.binding.busExpandImage.setImageResource(R.drawable.down);
|
||||
holder.binding.expandContent.removeAllViews();
|
||||
}
|
||||
} else if (item.isRailway()) {//火车
|
||||
if (!item.isArrowExpend()) {
|
||||
item.setArrowExpend(true);
|
||||
holder.binding.busExpandImage.setImageResource(R.drawable.up);
|
||||
addRailwayStation(item.getRailway().getDeparturestop(), holder.binding.expandContent);
|
||||
for (RailwayStationItem station : item.getRailway().getViastops()) {
|
||||
addRailwayStation(station, holder.binding.expandContent);
|
||||
}
|
||||
addRailwayStation(item.getRailway().getArrivalstop(), holder.binding.expandContent);
|
||||
|
||||
} else {
|
||||
item.setArrowExpend(false);
|
||||
holder.binding.busExpandImage.setImageResource(R.drawable.down);
|
||||
holder.binding.expandContent.removeAllViews();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加公交车站
|
||||
* @param station
|
||||
* @param expandContent
|
||||
*/
|
||||
private void addBusStation(BusStationItem station, LinearLayout expandContent) {
|
||||
LinearLayout ll = (LinearLayout) View.inflate(getContext(),
|
||||
R.layout.item_segment_ex, null);
|
||||
TextView tv = ll.findViewById(R.id.bus_line_station_name);
|
||||
tv.setText(station.getBusStationName());
|
||||
expandContent.addView(ll);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加火车站
|
||||
* @param station
|
||||
* @param expandContent
|
||||
*/
|
||||
private void addRailwayStation(RailwayStationItem station, LinearLayout expandContent) {
|
||||
LinearLayout ll = (LinearLayout) View.inflate(getContext(),
|
||||
R.layout.item_segment_ex, null);
|
||||
TextView tv = ll
|
||||
.findViewById(R.id.bus_line_station_name);
|
||||
tv.setText(station.getName() + " " + getRailwayTime(station.getTime()));
|
||||
expandContent.addView(ll);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取铁路时间
|
||||
* @param time
|
||||
* @return
|
||||
*/
|
||||
public static String getRailwayTime(String time) {
|
||||
return time.substring(0, 2) + ":" + time.substring(2, time.length());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mItemList == null || mItemList.isEmpty() ? 0 : mItemList.size();
|
||||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
ItemSegmentBinding binding;
|
||||
|
||||
public ViewHolder(ItemSegmentBinding itemView) {
|
||||
super(itemView.getRoot());
|
||||
this.binding = itemView;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package com.example.mangowalking.adapter;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.amap.api.services.route.WalkStep;
|
||||
import com.example.mangowalking.R;
|
||||
import com.example.mangowalking.databinding.ItemSegmentBinding;
|
||||
import com.example.mangowalking.utils.MapUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 步行段列表适配器
|
||||
*/
|
||||
public class WalkSegmentListAdapter extends RecyclerView.Adapter<WalkSegmentListAdapter.ViewHolder> {
|
||||
|
||||
private List<WalkStep> mItemList;
|
||||
|
||||
public WalkSegmentListAdapter(List<WalkStep> data) {
|
||||
this.mItemList = data;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new ViewHolder(ItemSegmentBinding.inflate(LayoutInflater.from(parent.getContext()), parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
WalkStep item = mItemList.get(position);
|
||||
if (position == 0) {
|
||||
holder.binding.busDirIcon.setImageResource(R.drawable.dir_start);
|
||||
holder.binding.busLineName.setText("出发");
|
||||
holder.binding.busDirIconUp.setVisibility(View.INVISIBLE);
|
||||
holder.binding.busDirIconDown.setVisibility(View.VISIBLE);
|
||||
holder.binding.busSegSplitLine.setVisibility(View.INVISIBLE);
|
||||
} else if (position == mItemList.size() - 1) {
|
||||
holder.binding.busDirIcon.setImageResource(R.drawable.dir_end);
|
||||
holder.binding.busLineName.setText("到达终点");
|
||||
holder.binding.busDirIconUp.setVisibility(View.VISIBLE);
|
||||
holder.binding.busDirIconDown.setVisibility(View.INVISIBLE);
|
||||
} else {
|
||||
holder.binding.busSegSplitLine.setVisibility(View.VISIBLE);
|
||||
holder.binding.busDirIconUp.setVisibility(View.VISIBLE);
|
||||
holder.binding.busDirIconDown.setVisibility(View.VISIBLE);
|
||||
String actionName = item.getAction();
|
||||
int resID = MapUtil.getWalkActionID(actionName);
|
||||
holder.binding.busDirIcon.setImageResource(resID);
|
||||
holder.binding.busLineName.setText(item.getInstruction());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getItemCount() {
|
||||
return mItemList == null || mItemList.isEmpty() ? 0 : mItemList.size();
|
||||
}
|
||||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
ItemSegmentBinding binding;
|
||||
|
||||
public ViewHolder(ItemSegmentBinding itemView) {
|
||||
super(itemView.getRoot());
|
||||
this.binding = itemView;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.example.mangowalking.overlay;
|
||||
|
||||
/**
|
||||
* 地图服务工具类
|
||||
*/
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
|
||||
import com.amap.api.maps.model.LatLng;
|
||||
import com.amap.api.services.core.LatLonPoint;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
class AMapServicesUtil {
|
||||
public static int BUFFER_SIZE = 2048;
|
||||
|
||||
public static byte[] inputStreamToByte(InputStream in) throws IOException {
|
||||
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||
byte[] data = new byte[BUFFER_SIZE];
|
||||
int count = -1;
|
||||
while ((count = in.read(data, 0, BUFFER_SIZE)) != -1){
|
||||
outStream.write(data, 0, count);
|
||||
}
|
||||
|
||||
data = null;
|
||||
return outStream.toByteArray();
|
||||
}
|
||||
public static LatLonPoint convertToLatLonPoint(LatLng latlon) {
|
||||
return new LatLonPoint(latlon.latitude, latlon.longitude);
|
||||
}
|
||||
public static LatLng convertToLatLng(LatLonPoint latLonPoint) {
|
||||
return new LatLng(latLonPoint.getLatitude(), latLonPoint.getLongitude());
|
||||
}
|
||||
public static ArrayList<LatLng> convertArrList(List<LatLonPoint> shapes) {
|
||||
ArrayList<LatLng> lineShapes = new ArrayList<LatLng>();
|
||||
for (LatLonPoint point : shapes) {
|
||||
LatLng latLngTemp = AMapServicesUtil.convertToLatLng(point);
|
||||
lineShapes.add(latLngTemp);
|
||||
}
|
||||
return lineShapes;
|
||||
}
|
||||
public static Bitmap zoomBitmap(Bitmap bitmap, float res) {
|
||||
if (bitmap == null) {
|
||||
return null;
|
||||
}
|
||||
int width, height;
|
||||
width = (int) (bitmap.getWidth() * res);
|
||||
height = (int) (bitmap.getHeight() * res);
|
||||
Bitmap newbmp = Bitmap.createScaledBitmap(bitmap, width, height, true);
|
||||
return newbmp;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,496 @@
|
||||
package com.example.mangowalking.overlay;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.amap.api.maps.AMap;
|
||||
import com.amap.api.maps.model.LatLng;
|
||||
import com.amap.api.maps.model.MarkerOptions;
|
||||
import com.amap.api.maps.model.PolylineOptions;
|
||||
import com.amap.api.services.busline.BusStationItem;
|
||||
import com.amap.api.services.core.LatLonPoint;
|
||||
import com.amap.api.services.route.BusPath;
|
||||
import com.amap.api.services.route.BusStep;
|
||||
import com.amap.api.services.route.Doorway;
|
||||
import com.amap.api.services.route.RailwayStationItem;
|
||||
import com.amap.api.services.route.RouteBusLineItem;
|
||||
import com.amap.api.services.route.RouteBusWalkItem;
|
||||
import com.amap.api.services.route.RouteRailwayItem;
|
||||
import com.amap.api.services.route.TaxiItem;
|
||||
import com.amap.api.services.route.WalkStep;
|
||||
import com.example.mangowalking.utils.MapUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 公交路线图层类。在高德地图API里,如果需要显示公交路线,可以用此类来创建公交路线图层。如不满足需求,也可以自己创建自定义的公交路线图层。
|
||||
* @since V2.1.0
|
||||
*/
|
||||
public class BusRouteOverlay extends RouteOverlay {
|
||||
|
||||
private BusPath busPath;
|
||||
private LatLng latLng;
|
||||
|
||||
/**
|
||||
* 通过此构造函数创建公交路线图层。
|
||||
* @param context 当前activity。
|
||||
* @param amap 地图对象。
|
||||
* @param path 公交路径规划的一个路段。详见搜索服务模块的路径查询包(com.amap.api.services.route)中的类<strong> <a href="../../../../../../Search/com/amap/api/services/route/BusPath.html" title="com.amap.api.services.route中的类">BusPath</a></strong>。
|
||||
* @param start 起点坐标。详见搜索服务模块的核心基础包(com.amap.api.services.core)中的类 <strong><a href="../../../../../../Search/com/amap/api/services/core/LatLonPoint.html" title="com.amap.api.services.core中的类">LatLonPoint</a></strong>。
|
||||
* @param end 终点坐标。详见搜索服务模块的核心基础包(com.amap.api.services.core)中的类 <strong><a href="../../../../../../Search/com/amap/api/services/core/LatLonPoint.html" title="com.amap.api.services.core中的类">LatLonPoint</a></strong>。
|
||||
* @since V2.1.0
|
||||
*/
|
||||
public BusRouteOverlay(Context context, AMap amap, BusPath path,
|
||||
LatLonPoint start, LatLonPoint end) {
|
||||
super(context);
|
||||
this.busPath = path;
|
||||
startPoint = MapUtil.convertToLatLng(start);
|
||||
endPoint = MapUtil.convertToLatLng(end);
|
||||
mAMap = amap;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加公交路线到地图上。
|
||||
* @since V2.1.0
|
||||
*/
|
||||
|
||||
public void addToMap() {
|
||||
/**
|
||||
* 绘制节点和线<br>
|
||||
* 细节情况较多<br>
|
||||
* 两个step之间,用step和step1区分<br>
|
||||
* 1.一个step内可能有步行和公交,然后有可能他们之间连接有断开<br>
|
||||
* 2.step的公交和step1的步行,有可能连接有断开<br>
|
||||
* 3.step和step1之间是公交换乘,且没有步行,需要把step的终点和step1的起点连起来<br>
|
||||
* 4.公交最后一站和终点间有步行,加入步行线路,还会有一些步行marker<br>
|
||||
* 5.公交最后一站和终点间无步行,之间连起来<br>
|
||||
*/
|
||||
try {
|
||||
List<BusStep> busSteps = busPath.getSteps();
|
||||
for (int i = 0; i < busSteps.size(); i++) {
|
||||
BusStep busStep = busSteps.get(i);
|
||||
if (i < busSteps.size() - 1) {
|
||||
BusStep busStep1 = busSteps.get(i + 1);// 取得当前下一个BusStep对象
|
||||
// 假如步行和公交之间连接有断开,就把步行最后一个经纬度点和公交第一个经纬度点连接起来,避免断线问题
|
||||
if (busStep.getWalk() != null
|
||||
&& busStep.getBusLine() != null) {
|
||||
checkWalkToBusline(busStep);
|
||||
}
|
||||
|
||||
// 假如公交和步行之间连接有断开,就把上一公交经纬度点和下一步行第一个经纬度点连接起来,避免断线问题
|
||||
if (busStep.getBusLine() != null
|
||||
&& busStep1.getWalk() != null
|
||||
&& busStep1.getWalk().getSteps().size() > 0) {
|
||||
checkBusLineToNextWalk(busStep, busStep1);
|
||||
}
|
||||
// 假如两个公交换乘中间没有步行,就把上一公交经纬度点和下一步公交第一个经纬度点连接起来,避免断线问题
|
||||
if (busStep.getBusLine() != null
|
||||
&& busStep1.getWalk() == null
|
||||
&& busStep1.getBusLine() != null) {
|
||||
checkBusEndToNextBusStart(busStep, busStep1);
|
||||
}
|
||||
// 和上面的很类似
|
||||
if (busStep.getBusLine() != null
|
||||
&& busStep1.getWalk() == null
|
||||
&& busStep1.getBusLine() != null) {
|
||||
checkBusToNextBusNoWalk(busStep, busStep1);
|
||||
}
|
||||
if (busStep.getBusLine() != null
|
||||
&& busStep1.getRailway() != null ) {
|
||||
checkBusLineToNextRailway(busStep, busStep1);
|
||||
}
|
||||
if (busStep1.getWalk() != null &&
|
||||
busStep1.getWalk().getSteps().size() > 0 &&
|
||||
busStep.getRailway() != null) {
|
||||
checkRailwayToNextWalk(busStep, busStep1);
|
||||
}
|
||||
|
||||
if ( busStep1.getRailway() != null &&
|
||||
busStep.getRailway() != null) {
|
||||
checkRailwayToNextRailway(busStep, busStep1);
|
||||
}
|
||||
|
||||
if (busStep.getRailway() != null &&
|
||||
busStep1.getTaxi() != null ){
|
||||
checkRailwayToNextTaxi(busStep, busStep1);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (busStep.getWalk() != null
|
||||
&& busStep.getWalk().getSteps().size() > 0) {
|
||||
addWalkSteps(busStep);
|
||||
} else {
|
||||
if (busStep.getBusLine() == null && busStep.getRailway() == null && busStep.getTaxi() == null) {
|
||||
addWalkPolyline(latLng, endPoint);
|
||||
}
|
||||
}
|
||||
if (busStep.getBusLine() != null) {
|
||||
RouteBusLineItem routeBusLineItem = busStep.getBusLine();
|
||||
addBusLineSteps(routeBusLineItem);
|
||||
addBusStationMarkers(routeBusLineItem);
|
||||
if (i == busSteps.size() - 1) {
|
||||
addWalkPolyline(MapUtil.convertToLatLng(getLastBuslinePoint(busStep)), endPoint);
|
||||
}
|
||||
}
|
||||
if (busStep.getRailway() != null) {
|
||||
addRailwayStep(busStep.getRailway());
|
||||
addRailwayMarkers(busStep.getRailway());
|
||||
if (i == busSteps.size() - 1) {
|
||||
addWalkPolyline(MapUtil.convertToLatLng(busStep.getRailway().getArrivalstop().getLocation()), endPoint);
|
||||
}
|
||||
}
|
||||
if (busStep.getTaxi() != null) {
|
||||
addTaxiStep(busStep.getTaxi());
|
||||
addTaxiMarkers(busStep.getTaxi());
|
||||
}
|
||||
}
|
||||
addStartAndEndMarker();
|
||||
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private void checkRailwayToNextTaxi(BusStep busStep, BusStep busStep1) {
|
||||
LatLonPoint railwayLastPoint = busStep.getRailway().getArrivalstop().getLocation();
|
||||
LatLonPoint taxiFirstPoint = busStep1.getTaxi().getOrigin();
|
||||
if (!railwayLastPoint.equals(taxiFirstPoint)) {
|
||||
addWalkPolyLineByLatLonPoints(railwayLastPoint, taxiFirstPoint);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkRailwayToNextRailway(BusStep busStep, BusStep busStep1) {
|
||||
LatLonPoint railwayLastPoint = busStep.getRailway().getArrivalstop().getLocation();
|
||||
LatLonPoint railwayFirstPoint = busStep1.getRailway().getDeparturestop().getLocation();
|
||||
if (!railwayLastPoint.equals(railwayFirstPoint)) {
|
||||
addWalkPolyLineByLatLonPoints(railwayLastPoint, railwayFirstPoint);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void checkBusLineToNextRailway(BusStep busStep, BusStep busStep1) {
|
||||
LatLonPoint busLastPoint = getLastBuslinePoint(busStep);
|
||||
LatLonPoint railwayFirstPoint = busStep1.getRailway().getDeparturestop().getLocation();
|
||||
if (!busLastPoint.equals(railwayFirstPoint)) {
|
||||
addWalkPolyLineByLatLonPoints(busLastPoint, railwayFirstPoint);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void checkRailwayToNextWalk(BusStep busStep, BusStep busStep1) {
|
||||
LatLonPoint railwayLastPoint = busStep.getRailway().getArrivalstop().getLocation();
|
||||
LatLonPoint walkFirstPoint = getFirstWalkPoint(busStep1);
|
||||
if (!railwayLastPoint.equals(walkFirstPoint)) {
|
||||
addWalkPolyLineByLatLonPoints(railwayLastPoint, walkFirstPoint);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void addRailwayStep(RouteRailwayItem railway) {
|
||||
List<LatLng> railwaylistpoint = new ArrayList<LatLng>();
|
||||
List<RailwayStationItem> railwayStationItems = new ArrayList<RailwayStationItem>();
|
||||
railwayStationItems.add(railway.getDeparturestop());
|
||||
railwayStationItems.addAll(railway.getViastops());
|
||||
railwayStationItems.add(railway.getArrivalstop());
|
||||
for (int i = 0; i < railwayStationItems.size(); i++) {
|
||||
railwaylistpoint.add(MapUtil.convertToLatLng(railwayStationItems.get(i).getLocation()));
|
||||
}
|
||||
addRailwayPolyline(railwaylistpoint);
|
||||
}
|
||||
|
||||
private void addTaxiStep(TaxiItem taxi){
|
||||
addPolyLine(new PolylineOptions().width(getRouteWidth())
|
||||
.color(getBusColor())
|
||||
.add(MapUtil.convertToLatLng(taxi.getOrigin()))
|
||||
.add(MapUtil.convertToLatLng(taxi.getDestination())));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param busStep
|
||||
*/
|
||||
private void addWalkSteps(BusStep busStep) {
|
||||
RouteBusWalkItem routeBusWalkItem = busStep.getWalk();
|
||||
List<WalkStep> walkSteps = routeBusWalkItem.getSteps();
|
||||
for (int j = 0; j < walkSteps.size(); j++) {
|
||||
WalkStep walkStep = walkSteps.get(j);
|
||||
if (j == 0) {
|
||||
LatLng latLng = MapUtil.convertToLatLng(walkStep
|
||||
.getPolyline().get(0));
|
||||
String road = walkStep.getRoad();// 道路名字
|
||||
String instruction = getWalkSnippet(walkSteps);// 步行导航信息
|
||||
addWalkStationMarkers(latLng, road, instruction);
|
||||
}
|
||||
|
||||
List<LatLng> listWalkPolyline = MapUtil
|
||||
.convertArrList(walkStep.getPolyline());
|
||||
this.latLng = listWalkPolyline.get(listWalkPolyline.size() - 1);
|
||||
|
||||
addWalkPolyline(listWalkPolyline);
|
||||
|
||||
// 假如步行前一段的终点和下的起点有断开,断画直线连接起来,避免断线问题
|
||||
if (j < walkSteps.size() - 1) {
|
||||
LatLng lastLatLng = listWalkPolyline.get(listWalkPolyline
|
||||
.size() - 1);
|
||||
LatLng firstlatLatLng = MapUtil
|
||||
.convertToLatLng(walkSteps.get(j + 1).getPolyline()
|
||||
.get(0));
|
||||
if (!(lastLatLng.equals(firstlatLatLng))) {
|
||||
addWalkPolyline(lastLatLng, firstlatLatLng);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一系列的bus PolyLine
|
||||
*
|
||||
* @param routeBusLineItem
|
||||
*/
|
||||
private void addBusLineSteps(RouteBusLineItem routeBusLineItem) {
|
||||
addBusLineSteps(routeBusLineItem.getPolyline());
|
||||
}
|
||||
|
||||
private void addBusLineSteps(List<LatLonPoint> listPoints) {
|
||||
if (listPoints.size() < 1) {
|
||||
return;
|
||||
}
|
||||
addPolyLine(new PolylineOptions().width(getRouteWidth())
|
||||
.color(getBusColor())
|
||||
.addAll(MapUtil.convertArrList(listPoints)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param latLng
|
||||
* marker
|
||||
* @param title
|
||||
* @param snippet
|
||||
*/
|
||||
private void addWalkStationMarkers(LatLng latLng, String title,
|
||||
String snippet) {
|
||||
addStationMarker(new MarkerOptions().position(latLng).title(title)
|
||||
.snippet(snippet).anchor(0.5f, 0.5f).visible(nodeIconVisible)
|
||||
.icon(getWalkBitmapDescriptor()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param routeBusLineItem
|
||||
*/
|
||||
private void addBusStationMarkers(RouteBusLineItem routeBusLineItem) {
|
||||
BusStationItem startBusStation = routeBusLineItem
|
||||
.getDepartureBusStation();
|
||||
LatLng position = MapUtil.convertToLatLng(startBusStation
|
||||
.getLatLonPoint());
|
||||
String title = routeBusLineItem.getBusLineName();
|
||||
String snippet = getBusSnippet(routeBusLineItem);
|
||||
|
||||
addStationMarker(new MarkerOptions().position(position).title(title)
|
||||
.snippet(snippet).anchor(0.5f, 0.5f).visible(nodeIconVisible)
|
||||
.icon(getBusBitmapDescriptor()));
|
||||
}
|
||||
|
||||
private void addTaxiMarkers(TaxiItem taxiItem) {
|
||||
|
||||
LatLng position = MapUtil.convertToLatLng(taxiItem
|
||||
.getOrigin());
|
||||
String title = taxiItem.getmSname()+"打车";
|
||||
String snippet = "到终点";
|
||||
|
||||
addStationMarker(new MarkerOptions().position(position).title(title)
|
||||
.snippet(snippet).anchor(0.5f, 0.5f).visible(nodeIconVisible)
|
||||
.icon(getDriveBitmapDescriptor()));
|
||||
}
|
||||
|
||||
private void addRailwayMarkers(RouteRailwayItem railway) {
|
||||
LatLng Departureposition = MapUtil.convertToLatLng(railway
|
||||
.getDeparturestop().getLocation());
|
||||
String Departuretitle = railway.getDeparturestop().getName()+"上车";
|
||||
String Departuresnippet = railway.getName();
|
||||
|
||||
addStationMarker(new MarkerOptions().position(Departureposition).title(Departuretitle)
|
||||
.snippet(Departuresnippet).anchor(0.5f, 0.5f).visible(nodeIconVisible)
|
||||
.icon(getBusBitmapDescriptor()));
|
||||
|
||||
|
||||
LatLng Arrivalposition = MapUtil.convertToLatLng(railway
|
||||
.getArrivalstop().getLocation());
|
||||
String Arrivaltitle = railway.getArrivalstop().getName()+"下车";
|
||||
String Arrivalsnippet = railway.getName();
|
||||
|
||||
addStationMarker(new MarkerOptions().position(Arrivalposition).title(Arrivaltitle)
|
||||
.snippet(Arrivalsnippet).anchor(0.5f, 0.5f).visible(nodeIconVisible)
|
||||
.icon(getBusBitmapDescriptor()));
|
||||
}
|
||||
/**
|
||||
* 如果换乘没有步行 检查bus最后一点和下一个step的bus起点是否一致
|
||||
*
|
||||
* @param busStep
|
||||
* @param busStep1
|
||||
*/
|
||||
private void checkBusToNextBusNoWalk(BusStep busStep, BusStep busStep1) {
|
||||
LatLng endbusLatLng = MapUtil
|
||||
.convertToLatLng(getLastBuslinePoint(busStep));
|
||||
LatLng startbusLatLng = MapUtil
|
||||
.convertToLatLng(getFirstBuslinePoint(busStep1));
|
||||
if (startbusLatLng.latitude - endbusLatLng.latitude > 0.0001
|
||||
|| startbusLatLng.longitude - endbusLatLng.longitude > 0.0001) {
|
||||
drawLineArrow(endbusLatLng, startbusLatLng);// 断线用带箭头的直线连?
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* checkBusToNextBusNoWalk 和这个类似
|
||||
*
|
||||
* @param busStep
|
||||
* @param busStep1
|
||||
*/
|
||||
private void checkBusEndToNextBusStart(BusStep busStep, BusStep busStep1) {
|
||||
LatLonPoint busLastPoint = getLastBuslinePoint(busStep);
|
||||
LatLng endbusLatLng = MapUtil.convertToLatLng(busLastPoint);
|
||||
LatLonPoint busFirstPoint = getFirstBuslinePoint(busStep1);
|
||||
LatLng startbusLatLng = MapUtil.convertToLatLng(busFirstPoint);
|
||||
if (!endbusLatLng.equals(startbusLatLng)) {
|
||||
drawLineArrow(endbusLatLng, startbusLatLng);//
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查bus最后一步和下一各step的步行起点是否一致
|
||||
*
|
||||
* @param busStep
|
||||
* @param busStep1
|
||||
*/
|
||||
private void checkBusLineToNextWalk(BusStep busStep, BusStep busStep1) {
|
||||
LatLonPoint busLastPoint = getLastBuslinePoint(busStep);
|
||||
LatLonPoint walkFirstPoint = getFirstWalkPoint(busStep1);
|
||||
if (!busLastPoint.equals(walkFirstPoint)) {
|
||||
addWalkPolyLineByLatLonPoints(busLastPoint, walkFirstPoint);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查 步行最后一点 和 bus的起点 是否一致
|
||||
*
|
||||
* @param busStep
|
||||
*/
|
||||
private void checkWalkToBusline(BusStep busStep) {
|
||||
LatLonPoint walkLastPoint = getLastWalkPoint(busStep);
|
||||
LatLonPoint buslineFirstPoint = getFirstBuslinePoint(busStep);
|
||||
|
||||
if (!walkLastPoint.equals(buslineFirstPoint)) {
|
||||
addWalkPolyLineByLatLonPoints(walkLastPoint, buslineFirstPoint);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param busStep1
|
||||
* @return
|
||||
*/
|
||||
private LatLonPoint getFirstWalkPoint(BusStep busStep1) {
|
||||
return busStep1.getWalk().getSteps().get(0).getPolyline().get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private void addWalkPolyLineByLatLonPoints(LatLonPoint pointFrom,
|
||||
LatLonPoint pointTo) {
|
||||
LatLng latLngFrom = MapUtil.convertToLatLng(pointFrom);
|
||||
LatLng latLngTo = MapUtil.convertToLatLng(pointTo);
|
||||
|
||||
addWalkPolyline(latLngFrom, latLngTo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param latLngFrom
|
||||
* @param latLngTo
|
||||
* @return
|
||||
*/
|
||||
private void addWalkPolyline(LatLng latLngFrom, LatLng latLngTo) {
|
||||
addPolyLine(new PolylineOptions().add(latLngFrom, latLngTo)
|
||||
.width(getRouteWidth()).color(getWalkColor()).setDottedLine(true));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param listWalkPolyline
|
||||
*/
|
||||
private void addWalkPolyline(List<LatLng> listWalkPolyline) {
|
||||
|
||||
addPolyLine(new PolylineOptions().addAll(listWalkPolyline)
|
||||
.color(getWalkColor()).width(getRouteWidth()).setDottedLine(true));
|
||||
}
|
||||
|
||||
private void addRailwayPolyline(List<LatLng> listPolyline) {
|
||||
|
||||
addPolyLine(new PolylineOptions().addAll(listPolyline)
|
||||
.color(getDriveColor()).width(getRouteWidth()));
|
||||
}
|
||||
|
||||
|
||||
private String getWalkSnippet(List<WalkStep> walkSteps) {
|
||||
float disNum = 0;
|
||||
for (WalkStep step : walkSteps) {
|
||||
disNum += step.getDistance();
|
||||
}
|
||||
return "\u6B65\u884C" + disNum + "\u7C73";
|
||||
}
|
||||
|
||||
public void drawLineArrow(LatLng latLngFrom, LatLng latLngTo) {
|
||||
|
||||
addPolyLine(new PolylineOptions().add(latLngFrom, latLngTo).width(3)
|
||||
.color(getBusColor()).width(getRouteWidth()));// 绘制直线
|
||||
}
|
||||
|
||||
private String getBusSnippet(RouteBusLineItem routeBusLineItem) {
|
||||
return "("
|
||||
+ routeBusLineItem.getDepartureBusStation().getBusStationName()
|
||||
+ "-->"
|
||||
+ routeBusLineItem.getArrivalBusStation().getBusStationName()
|
||||
+ ") \u7ECF\u8FC7" + (routeBusLineItem.getPassStationNum() + 1)
|
||||
+ "\u7AD9";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param busStep
|
||||
* @return
|
||||
*/
|
||||
private LatLonPoint getLastWalkPoint(BusStep busStep) {
|
||||
|
||||
List<WalkStep> walkSteps = busStep.getWalk().getSteps();
|
||||
WalkStep walkStep = walkSteps.get(walkSteps.size() - 1);
|
||||
List<LatLonPoint> lonPoints = walkStep.getPolyline();
|
||||
return lonPoints.get(lonPoints.size() - 1);
|
||||
}
|
||||
|
||||
private LatLonPoint getExitPoint(BusStep busStep) {
|
||||
Doorway doorway = busStep.getExit();
|
||||
if (doorway == null) {
|
||||
return null;
|
||||
}
|
||||
return doorway.getLatLonPoint();
|
||||
}
|
||||
|
||||
private LatLonPoint getLastBuslinePoint(BusStep busStep) {
|
||||
List<LatLonPoint> lonPoints = busStep.getBusLine().getPolyline();
|
||||
|
||||
return lonPoints.get(lonPoints.size() - 1);
|
||||
}
|
||||
|
||||
private LatLonPoint getEntrancePoint(BusStep busStep) {
|
||||
Doorway doorway = busStep.getEntrance();
|
||||
if (doorway == null) {
|
||||
return null;
|
||||
}
|
||||
return doorway.getLatLonPoint();
|
||||
}
|
||||
|
||||
private LatLonPoint getFirstBuslinePoint(BusStep busStep) {
|
||||
return busStep.getBusLine().getPolyline().get(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
package com.example.mangowalking.overlay;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Color;
|
||||
|
||||
import com.amap.api.maps.AMap;
|
||||
import com.amap.api.maps.CameraUpdateFactory;
|
||||
import com.amap.api.maps.model.BitmapDescriptor;
|
||||
import com.amap.api.maps.model.BitmapDescriptorFactory;
|
||||
import com.amap.api.maps.model.LatLng;
|
||||
import com.amap.api.maps.model.LatLngBounds;
|
||||
import com.amap.api.maps.model.Marker;
|
||||
import com.amap.api.maps.model.MarkerOptions;
|
||||
import com.amap.api.maps.model.Polyline;
|
||||
import com.amap.api.maps.model.PolylineOptions;
|
||||
import com.example.mangowalking.R;
|
||||
|
||||
/**
|
||||
* 路线图层叠加
|
||||
*/
|
||||
public class RouteOverlay {
|
||||
protected List<Marker> stationMarkers = new ArrayList<Marker>();
|
||||
protected List<Polyline> allPolyLines = new ArrayList<Polyline>();
|
||||
protected Marker startMarker;
|
||||
protected Marker endMarker;
|
||||
protected LatLng startPoint;
|
||||
protected LatLng endPoint;
|
||||
protected AMap mAMap;
|
||||
private Context mContext;
|
||||
private Bitmap startBit, endBit, busBit, walkBit, driveBit;
|
||||
protected boolean nodeIconVisible = true;
|
||||
|
||||
public RouteOverlay(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
/**
|
||||
* 去掉BusRouteOverlay上所有的Marker。
|
||||
* @since V2.1.0
|
||||
*/
|
||||
public void removeFromMap() {
|
||||
if (startMarker != null) {
|
||||
startMarker.remove();
|
||||
|
||||
}
|
||||
if (endMarker != null) {
|
||||
endMarker.remove();
|
||||
}
|
||||
for (Marker marker : stationMarkers) {
|
||||
marker.remove();
|
||||
}
|
||||
for (Polyline line : allPolyLines) {
|
||||
line.remove();
|
||||
}
|
||||
destroyBit();
|
||||
}
|
||||
|
||||
private void destroyBit() {
|
||||
if (startBit != null) {
|
||||
startBit.recycle();
|
||||
startBit = null;
|
||||
}
|
||||
if (endBit != null) {
|
||||
endBit.recycle();
|
||||
endBit = null;
|
||||
}
|
||||
if (busBit != null) {
|
||||
busBit.recycle();
|
||||
busBit = null;
|
||||
}
|
||||
if (walkBit != null) {
|
||||
walkBit.recycle();
|
||||
walkBit = null;
|
||||
}
|
||||
if (driveBit != null) {
|
||||
driveBit.recycle();
|
||||
driveBit = null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 给起点Marker设置图标,并返回更换图标的图片。如不用默认图片,需要重写此方法。
|
||||
* @return 更换的Marker图片。
|
||||
* @since V2.1.0
|
||||
*/
|
||||
protected BitmapDescriptor getStartBitmapDescriptor() {
|
||||
return BitmapDescriptorFactory.fromResource(R.drawable.amap_start);
|
||||
}
|
||||
/**
|
||||
* 给终点Marker设置图标,并返回更换图标的图片。如不用默认图片,需要重写此方法。
|
||||
* @return 更换的Marker图片。
|
||||
* @since V2.1.0
|
||||
*/
|
||||
protected BitmapDescriptor getEndBitmapDescriptor() {
|
||||
return BitmapDescriptorFactory.fromResource(R.drawable.amap_end);
|
||||
}
|
||||
/**
|
||||
* 给公交Marker设置图标,并返回更换图标的图片。如不用默认图片,需要重写此方法。
|
||||
* @return 更换的Marker图片。
|
||||
* @since V2.1.0
|
||||
*/
|
||||
protected BitmapDescriptor getBusBitmapDescriptor() {
|
||||
return BitmapDescriptorFactory.fromResource(R.drawable.amap_bus);
|
||||
}
|
||||
/**
|
||||
* 给步行Marker设置图标,并返回更换图标的图片。如不用默认图片,需要重写此方法。
|
||||
* @return 更换的Marker图片。
|
||||
* @since V2.1.0
|
||||
*/
|
||||
protected BitmapDescriptor getWalkBitmapDescriptor() {
|
||||
return BitmapDescriptorFactory.fromResource(R.drawable.amap_man);
|
||||
}
|
||||
|
||||
protected BitmapDescriptor getDriveBitmapDescriptor() {
|
||||
return BitmapDescriptorFactory.fromResource(R.drawable.amap_car);
|
||||
}
|
||||
|
||||
protected void addStartAndEndMarker() {
|
||||
startMarker = mAMap.addMarker((new MarkerOptions())
|
||||
.position(startPoint).icon(getStartBitmapDescriptor())
|
||||
.title("\u8D77\u70B9"));
|
||||
// startMarker.showInfoWindow();
|
||||
|
||||
endMarker = mAMap.addMarker((new MarkerOptions()).position(endPoint)
|
||||
.icon(getEndBitmapDescriptor()).title("\u7EC8\u70B9"));
|
||||
// mAMap.moveCamera(CameraUpdateFactory.newLatLngZoom(startPoint,
|
||||
// getShowRouteZoom()));
|
||||
}
|
||||
/**
|
||||
* 移动镜头到当前的视角。
|
||||
* @since V2.1.0
|
||||
*/
|
||||
public void zoomToSpan() {
|
||||
if (startPoint != null) {
|
||||
if (mAMap == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
LatLngBounds bounds = getLatLngBounds();
|
||||
mAMap.animateCamera(CameraUpdateFactory
|
||||
.newLatLngBounds(bounds, 100));
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected LatLngBounds getLatLngBounds() {
|
||||
LatLngBounds.Builder b = LatLngBounds.builder();
|
||||
b.include(new LatLng(startPoint.latitude, startPoint.longitude));
|
||||
b.include(new LatLng(endPoint.latitude, endPoint.longitude));
|
||||
return b.build();
|
||||
}
|
||||
/**
|
||||
* 路段节点图标控制显示接口。
|
||||
* @param visible true为显示节点图标,false为不显示。
|
||||
* @since V2.3.1
|
||||
*/
|
||||
public void setNodeIconVisibility(boolean visible) {
|
||||
try {
|
||||
nodeIconVisible = visible;
|
||||
if (this.stationMarkers != null && this.stationMarkers.size() > 0) {
|
||||
for (int i = 0; i < this.stationMarkers.size(); i++) {
|
||||
this.stationMarkers.get(i).setVisible(visible);
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
protected void addStationMarker(MarkerOptions options) {
|
||||
if(options == null) {
|
||||
return;
|
||||
}
|
||||
Marker marker = mAMap.addMarker(options);
|
||||
if(marker != null) {
|
||||
stationMarkers.add(marker);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected void addPolyLine(PolylineOptions options) {
|
||||
if(options == null) {
|
||||
return;
|
||||
}
|
||||
Polyline polyline = mAMap.addPolyline(options);
|
||||
if(polyline != null) {
|
||||
allPolyLines.add(polyline);
|
||||
}
|
||||
}
|
||||
|
||||
protected float getRouteWidth() {
|
||||
return 18f;
|
||||
}
|
||||
|
||||
protected int getWalkColor() {
|
||||
return Color.parseColor("#6db74d");
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义路线颜色。
|
||||
* return 自定义路线颜色。
|
||||
* @since V2.2.1
|
||||
*/
|
||||
protected int getBusColor() {
|
||||
return Color.parseColor("#537edc");
|
||||
}
|
||||
|
||||
protected int getDriveColor() {
|
||||
return Color.parseColor("#537edc");
|
||||
}
|
||||
|
||||
// protected int getShowRouteZoom() {
|
||||
// return 15;
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
package com.example.mangowalking.overlay;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.amap.api.maps.AMap;
|
||||
import com.amap.api.maps.model.BitmapDescriptor;
|
||||
import com.amap.api.maps.model.LatLng;
|
||||
import com.amap.api.maps.model.MarkerOptions;
|
||||
import com.amap.api.maps.model.PolylineOptions;
|
||||
import com.amap.api.services.core.LatLonPoint;
|
||||
import com.amap.api.services.route.WalkPath;
|
||||
import com.amap.api.services.route.WalkStep;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
/**
|
||||
* 步行路线图层类。在高德地图API里,如果要显示步行路线规划,可以用此类来创建步行路线图层。如不满足需求,也可以自己创建自定义的步行路线图层。
|
||||
* @since V2.1.0
|
||||
*/
|
||||
public class WalkRouteOverlay extends RouteOverlay {
|
||||
|
||||
private PolylineOptions mPolylineOptions;
|
||||
|
||||
private BitmapDescriptor walkStationDescriptor= null;
|
||||
|
||||
private WalkPath walkPath;
|
||||
/**
|
||||
* 通过此构造函数创建步行路线图层。
|
||||
* @param context 当前activity。
|
||||
* @param amap 地图对象。
|
||||
* @param path 步行路线规划的一个方案。详见搜索服务模块的路径查询包(com.amap.api.services.route)中的类 <strong><a href="../../../../../../Search/com/amap/api/services/route/WalkStep.html" title="com.amap.api.services.route中的类">WalkStep</a></strong>。
|
||||
* @param start 起点。详见搜索服务模块的核心基础包(com.amap.api.services.core)中的类<strong><a href="../../../../../../Search/com/amap/api/services/core/LatLonPoint.html" title="com.amap.api.services.core中的类">LatLonPoint</a></strong>。
|
||||
* @param end 终点。详见搜索服务模块的核心基础包(com.amap.api.services.core)中的类<strong><a href="../../../../../../Search/com/amap/api/services/core/LatLonPoint.html" title="com.amap.api.services.core中的类">LatLonPoint</a></strong>。
|
||||
* @since V2.1.0
|
||||
*/
|
||||
public WalkRouteOverlay(Context context, AMap amap, WalkPath path,
|
||||
LatLonPoint start, LatLonPoint end) {
|
||||
super(context);
|
||||
this.mAMap = amap;
|
||||
this.walkPath = path;
|
||||
startPoint = AMapServicesUtil.convertToLatLng(start);
|
||||
endPoint = AMapServicesUtil.convertToLatLng(end);
|
||||
}
|
||||
/**
|
||||
* 添加步行路线到地图中。
|
||||
* @since V2.1.0
|
||||
*/
|
||||
public void addToMap() {
|
||||
|
||||
initPolylineOptions();
|
||||
try {
|
||||
List<WalkStep> walkPaths = walkPath.getSteps();
|
||||
for (int i = 0; i < walkPaths.size(); i++) {
|
||||
WalkStep walkStep = walkPaths.get(i);
|
||||
LatLng latLng = AMapServicesUtil.convertToLatLng(walkStep
|
||||
.getPolyline().get(0));
|
||||
|
||||
addWalkStationMarkers(walkStep, latLng);
|
||||
addWalkPolyLines(walkStep);
|
||||
|
||||
}
|
||||
addStartAndEndMarker();
|
||||
|
||||
showPolyline();
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查这一步的最后一点和下一步的起始点之间是否存在空隙
|
||||
*/
|
||||
private void checkDistanceToNextStep(WalkStep walkStep,
|
||||
WalkStep walkStep1) {
|
||||
LatLonPoint lastPoint = getLastWalkPoint(walkStep);
|
||||
LatLonPoint nextFirstPoint = getFirstWalkPoint(walkStep1);
|
||||
if (!(lastPoint.equals(nextFirstPoint))) {
|
||||
addWalkPolyLine(lastPoint, nextFirstPoint);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param walkStep
|
||||
* @return
|
||||
*/
|
||||
private LatLonPoint getLastWalkPoint(WalkStep walkStep) {
|
||||
return walkStep.getPolyline().get(walkStep.getPolyline().size() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param walkStep
|
||||
* @return
|
||||
*/
|
||||
private LatLonPoint getFirstWalkPoint(WalkStep walkStep) {
|
||||
return walkStep.getPolyline().get(0);
|
||||
}
|
||||
|
||||
|
||||
private void addWalkPolyLine(LatLonPoint pointFrom, LatLonPoint pointTo) {
|
||||
addWalkPolyLine(AMapServicesUtil.convertToLatLng(pointFrom), AMapServicesUtil.convertToLatLng(pointTo));
|
||||
}
|
||||
|
||||
private void addWalkPolyLine(LatLng latLngFrom, LatLng latLngTo) {
|
||||
mPolylineOptions.add(latLngFrom, latLngTo);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param walkStep
|
||||
*/
|
||||
private void addWalkPolyLines(WalkStep walkStep) {
|
||||
mPolylineOptions.addAll(AMapServicesUtil.convertArrList(walkStep.getPolyline()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param walkStep
|
||||
* @param position
|
||||
*/
|
||||
private void addWalkStationMarkers(WalkStep walkStep, LatLng position) {
|
||||
addStationMarker(new MarkerOptions()
|
||||
.position(position)
|
||||
.title("\u65B9\u5411:" + walkStep.getAction()
|
||||
+ "\n\u9053\u8DEF:" + walkStep.getRoad())
|
||||
.snippet(walkStep.getInstruction()).visible(nodeIconVisible)
|
||||
.anchor(0.5f, 0.5f).icon(walkStationDescriptor));
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化线段属性
|
||||
*/
|
||||
private void initPolylineOptions() {
|
||||
|
||||
if(walkStationDescriptor == null) {
|
||||
walkStationDescriptor = getWalkBitmapDescriptor();
|
||||
}
|
||||
|
||||
mPolylineOptions = null;
|
||||
|
||||
mPolylineOptions = new PolylineOptions();
|
||||
mPolylineOptions.color(getWalkColor()).width(getRouteWidth());
|
||||
}
|
||||
|
||||
|
||||
private void showPolyline() {
|
||||
addPolyLine(mPolylineOptions);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package com.example.mangowalking.utils;
|
||||
|
||||
public class ChString {
|
||||
public static final String Kilometer = "\u516c\u91cc";// "公里";
|
||||
public static final String Meter = "\u7c73";// "米";
|
||||
public static final String ByFoot = "\u6b65\u884c";// "步行";
|
||||
public static final String To = "\u53bb\u5f80";// "去往";
|
||||
public static final String Station = "\u8f66\u7ad9";// "车站";
|
||||
public static final String TargetPlace = "\u76ee\u7684\u5730";// "目的地";
|
||||
public static final String StartPlace = "\u51fa\u53d1\u5730";// "出发地";
|
||||
public static final String About = "\u5927\u7ea6";// "大约";
|
||||
public static final String Direction = "\u65b9\u5411";// "方向";
|
||||
|
||||
public static final String GetOn = "\u4e0a\u8f66";// "上车";
|
||||
public static final String GetOff = "\u4e0b\u8f66";// "下车";
|
||||
public static final String Zhan = "\u7ad9";// "站";
|
||||
|
||||
public static final String cross = "\u4ea4\u53c9\u8def\u53e3"; // 交叉路口
|
||||
public static final String type = "\u7c7b\u522b"; // 类别
|
||||
public static final String address = "\u5730\u5740"; // 地址
|
||||
public static final String PrevStep = "\u4e0a\u4e00\u6b65";
|
||||
public static final String NextStep = "\u4e0b\u4e00\u6b65";
|
||||
public static final String Gong = "\u516c\u4ea4";
|
||||
public static final String ByBus = "\u4e58\u8f66";
|
||||
public static final String Arrive = "\u5230\u8FBE";// 到达
|
||||
}
|
||||
150
app/src/main/java/com/example/mangowalking/utils/MapUtil.java
Normal file
@@ -0,0 +1,150 @@
|
||||
package com.example.mangowalking.utils;
|
||||
|
||||
import com.amap.api.maps.model.LatLng;
|
||||
import com.amap.api.services.core.LatLonPoint;
|
||||
import com.example.mangowalking.R;
|
||||
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 地图帮助类
|
||||
* @author llw
|
||||
*/
|
||||
public class MapUtil {
|
||||
|
||||
/**
|
||||
* 把LatLng对象转化为LatLonPoint对象
|
||||
*/
|
||||
public static LatLonPoint convertToLatLonPoint(LatLng latLng) {
|
||||
return new LatLonPoint(latLng.latitude, latLng.longitude);
|
||||
}
|
||||
|
||||
/**
|
||||
* 把LatLonPoint对象转化为LatLon对象
|
||||
*/
|
||||
public static LatLng convertToLatLng(LatLonPoint latLonPoint) {
|
||||
return new LatLng(latLonPoint.getLatitude(), latLonPoint.getLongitude());
|
||||
}
|
||||
|
||||
public static String getFriendlyTime(int second) {
|
||||
if (second > 3600) {
|
||||
int hour = second / 3600;
|
||||
int miniate = (second % 3600) / 60;
|
||||
return hour + "小时" + miniate + "分钟";
|
||||
}
|
||||
if (second >= 60) {
|
||||
int miniate = second / 60;
|
||||
return miniate + "分钟";
|
||||
}
|
||||
return second + "秒";
|
||||
}
|
||||
|
||||
public static String getFriendlyLength(int lenMeter) {
|
||||
if (lenMeter > 10000) // 10 km
|
||||
{
|
||||
int dis = lenMeter / 1000;
|
||||
return dis + ChString.Kilometer;
|
||||
}
|
||||
|
||||
if (lenMeter > 1000) {
|
||||
float dis = (float) lenMeter / 1000;
|
||||
DecimalFormat fnum = new DecimalFormat("##0.0");
|
||||
String dstr = fnum.format(dis);
|
||||
return dstr + ChString.Kilometer;
|
||||
}
|
||||
|
||||
if (lenMeter > 100) {
|
||||
int dis = lenMeter / 50 * 50;
|
||||
return dis + ChString.Meter;
|
||||
}
|
||||
|
||||
int dis = lenMeter / 10 * 10;
|
||||
if (dis == 0) {
|
||||
dis = 10;
|
||||
}
|
||||
|
||||
return dis + ChString.Meter;
|
||||
}
|
||||
/**
|
||||
* 把集合体的LatLonPoint转化为集合体的LatLng
|
||||
*/
|
||||
public static ArrayList<LatLng> convertArrList(List<LatLonPoint> shapes) {
|
||||
ArrayList<LatLng> lineShapes = new ArrayList<LatLng>();
|
||||
for (LatLonPoint point : shapes) {
|
||||
LatLng latLngTemp = convertToLatLng(point);
|
||||
lineShapes.add(latLngTemp);
|
||||
}
|
||||
return lineShapes;
|
||||
}
|
||||
|
||||
public static int getWalkActionID(String actionName) {
|
||||
if (actionName == null || actionName.equals("")) {
|
||||
return R.drawable.dir13;
|
||||
}
|
||||
if ("左转".equals(actionName)) {
|
||||
return R.drawable.dir2;
|
||||
}
|
||||
if ("右转".equals(actionName)) {
|
||||
return R.drawable.dir1;
|
||||
}
|
||||
if ("向左前方".equals(actionName) || "靠左".equals(actionName) || actionName.contains("向左前方")) {
|
||||
return R.drawable.dir6;
|
||||
}
|
||||
if ("向右前方".equals(actionName) || "靠右".equals(actionName) || actionName.contains("向右前方")) {
|
||||
return R.drawable.dir5;
|
||||
}
|
||||
if ("向左后方".equals(actionName)|| actionName.contains("向左后方")) {
|
||||
return R.drawable.dir7;
|
||||
}
|
||||
if ("向右后方".equals(actionName)|| actionName.contains("向右后方")) {
|
||||
return R.drawable.dir8;
|
||||
}
|
||||
if ("直行".equals(actionName)) {
|
||||
return R.drawable.dir3;
|
||||
}
|
||||
if ("通过人行横道".equals(actionName)) {
|
||||
return R.drawable.dir9;
|
||||
}
|
||||
if ("通过过街天桥".equals(actionName)) {
|
||||
return R.drawable.dir11;
|
||||
}
|
||||
if ("通过地下通道".equals(actionName)) {
|
||||
return R.drawable.dir10;
|
||||
}
|
||||
return R.drawable.dir13;
|
||||
}
|
||||
|
||||
public static int getDriveActionID(String actionName) {
|
||||
if (actionName == null || actionName.isEmpty()) {
|
||||
return R.drawable.dir3;
|
||||
}
|
||||
if ("左转".equals(actionName)) {
|
||||
return R.drawable.dir2;
|
||||
}
|
||||
if ("右转".equals(actionName)) {
|
||||
return R.drawable.dir1;
|
||||
}
|
||||
if ("向左前方行驶".equals(actionName) || "靠左".equals(actionName)) {
|
||||
return R.drawable.dir6;
|
||||
}
|
||||
if ("向右前方行驶".equals(actionName) || "靠右".equals(actionName)) {
|
||||
return R.drawable.dir5;
|
||||
}
|
||||
if ("向左后方行驶".equals(actionName) || "左转调头".equals(actionName)) {
|
||||
return R.drawable.dir7;
|
||||
}
|
||||
if ("向右后方行驶".equals(actionName)) {
|
||||
return R.drawable.dir8;
|
||||
}
|
||||
if ("直行".equals(actionName)) {
|
||||
return R.drawable.dir3;
|
||||
}
|
||||
if ("减速行驶".equals(actionName)) {
|
||||
return R.drawable.dir4;
|
||||
}
|
||||
return R.drawable.dir3;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
package com.example.mangowalking.utils;
|
||||
|
||||
import com.amap.api.services.route.BusStep;
|
||||
|
||||
public class SchemeBusStep extends BusStep {
|
||||
|
||||
private boolean isWalk = false;
|
||||
private boolean isBus = false;
|
||||
private boolean israilway = false;
|
||||
private boolean istaxi = false;
|
||||
private boolean isStart = false;
|
||||
private boolean isEnd = false;
|
||||
private boolean arrowExpend = false;
|
||||
|
||||
public SchemeBusStep(BusStep step) {
|
||||
if (step != null) {
|
||||
this.setBusLine(step.getBusLine());
|
||||
this.setWalk(step.getWalk());
|
||||
this.setRailway(step.getRailway());
|
||||
this.setTaxi(step.getTaxi());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isArrowExpend() {
|
||||
return arrowExpend;
|
||||
}
|
||||
|
||||
public void setArrowExpend(boolean arrowExpend) {
|
||||
this.arrowExpend = arrowExpend;
|
||||
}
|
||||
|
||||
public boolean isWalk() {
|
||||
return isWalk;
|
||||
}
|
||||
|
||||
public void setWalk(boolean isWalk) {
|
||||
this.isWalk = isWalk;
|
||||
}
|
||||
|
||||
public boolean isBus() {
|
||||
return isBus;
|
||||
}
|
||||
|
||||
public void setBus(boolean isBus) {
|
||||
this.isBus = isBus;
|
||||
}
|
||||
|
||||
public boolean isStart() {
|
||||
return isStart;
|
||||
}
|
||||
|
||||
public void setStart(boolean isStart) {
|
||||
this.isStart = isStart;
|
||||
}
|
||||
|
||||
public boolean isEnd() {
|
||||
return isEnd;
|
||||
}
|
||||
|
||||
public void setEnd(boolean isEnd) {
|
||||
this.isEnd = isEnd;
|
||||
}
|
||||
|
||||
public boolean isRailway() {
|
||||
return israilway;
|
||||
}
|
||||
|
||||
public boolean isTaxi() {
|
||||
return istaxi;
|
||||
}
|
||||
|
||||
public void setRailway(boolean israilway) {
|
||||
this.israilway = israilway;
|
||||
}
|
||||
|
||||
public void setTaxi(boolean istaxi) {
|
||||
this.istaxi = istaxi;
|
||||
}
|
||||
|
||||
}
|
||||
BIN
app/src/main/res/drawable/amap_bus.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
app/src/main/res/drawable/amap_car.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/drawable/amap_end.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
app/src/main/res/drawable/amap_man.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/drawable/amap_ride.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/drawable/amap_start.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
app/src/main/res/drawable/amap_through.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
app/src/main/res/drawable/amap_train.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
app/src/main/res/drawable/dir1.png
Normal file
|
After Width: | Height: | Size: 702 B |
BIN
app/src/main/res/drawable/dir10.png
Normal file
|
After Width: | Height: | Size: 910 B |
BIN
app/src/main/res/drawable/dir11.png
Normal file
|
After Width: | Height: | Size: 941 B |
BIN
app/src/main/res/drawable/dir12.png
Normal file
|
After Width: | Height: | Size: 865 B |
BIN
app/src/main/res/drawable/dir13.png
Normal file
|
After Width: | Height: | Size: 883 B |
BIN
app/src/main/res/drawable/dir14.png
Normal file
|
After Width: | Height: | Size: 949 B |
BIN
app/src/main/res/drawable/dir15.png
Normal file
|
After Width: | Height: | Size: 849 B |
BIN
app/src/main/res/drawable/dir16.png
Normal file
|
After Width: | Height: | Size: 742 B |
BIN
app/src/main/res/drawable/dir2.png
Normal file
|
After Width: | Height: | Size: 699 B |
BIN
app/src/main/res/drawable/dir3.png
Normal file
|
After Width: | Height: | Size: 712 B |
BIN
app/src/main/res/drawable/dir4.png
Normal file
|
After Width: | Height: | Size: 711 B |
BIN
app/src/main/res/drawable/dir5.png
Normal file
|
After Width: | Height: | Size: 838 B |
BIN
app/src/main/res/drawable/dir6.png
Normal file
|
After Width: | Height: | Size: 832 B |
BIN
app/src/main/res/drawable/dir7.png
Normal file
|
After Width: | Height: | Size: 791 B |
BIN
app/src/main/res/drawable/dir8.png
Normal file
|
After Width: | Height: | Size: 824 B |
BIN
app/src/main/res/drawable/dir9.png
Normal file
|
After Width: | Height: | Size: 942 B |
BIN
app/src/main/res/drawable/dir_end.png
Normal file
|
After Width: | Height: | Size: 604 B |
BIN
app/src/main/res/drawable/dir_start.png
Normal file
|
After Width: | Height: | Size: 601 B |
BIN
app/src/main/res/drawable/dir_station.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/drawable/down.png
Normal file
|
After Width: | Height: | Size: 226 B |
BIN
app/src/main/res/drawable/end.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
5
app/src/main/res/drawable/et_bg.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<shape xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<corners android:radius="8dp"/>
|
||||
<solid android:color="#E4E4E4"/>
|
||||
</shape>
|
||||
BIN
app/src/main/res/drawable/gps_point.png
Normal file
|
After Width: | Height: | Size: 2.3 KiB |
13
app/src/main/res/drawable/ic_black_back.xml
Normal file
@@ -0,0 +1,13 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:autoMirrored="true"
|
||||
android:tint="#000000"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M16.62,2.99c-0.49,-0.49 -1.28,-0.49 -1.77,0L6.54,11.3c-0.39,0.39 -0.39,1.02 0,1.41l8.31,8.31c0.49,0.49 1.28,0.49 1.77,0s0.49,-1.28 0,-1.77L9.38,12l7.25,-7.25c0.48,-0.48 0.48,-1.28 -0.01,-1.76z" />
|
||||
|
||||
</vector>
|
||||
12
app/src/main/res/drawable/ic_blue_open.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="18dp"
|
||||
android:height="18dp"
|
||||
android:autoMirrored="true"
|
||||
android:tint="#4C90F9"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M7.38,21.01c0.49,0.49 1.28,0.49 1.77,0l8.31,-8.31c0.39,-0.39 0.39,-1.02 0,-1.41L9.15,2.98c-0.49,-0.49 -1.28,-0.49 -1.77,0s-0.49,1.28 0,1.77L14.62,12l-7.25,7.25c-0.48,0.48 -0.48,1.28 0.01,1.76z" />
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/ic_clear.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="#323233"
|
||||
android:pathData="M279.8,206.6a57.6,57.6 0,1 1,57.6 57.3,56.9 56.9,0 0,1 -57.6,-57.3zM572.5,954.6c0,1 -1.9,1.9 -2.9,1.9l-97.6,-58.3a3.6,3.6 0,0 1,-1 -2.9c8.8,-19.4 97.6,-203 87.8,-193.3a1243,1243 0,0 0,-116.1 139.9l-26.3,35.9s-102.4,-69 -134.7,-111.7c0,-1 -1,-1 0,-1.9 20.5,-25.3 129.8,-166.1 129.8,-166.1l-184.4,110.7h-2.9c-8.8,-9.7 -70.3,-77.7 -88.8,-109.8v-1.9c17.6,-14.6 117.1,-98.1 117.1,-98.1l-140.5,49.5a3.6,3.6 0,0 1,-2.9 -1l-51.7,-97.1a1.9,1.9 0,0 1,1 -2.9c24.4,-4.8 230.3,-47.6 330.8,-116.6 2.5,-1.7 5.8,-1.3 7.8,1l287.9,286.5c2.3,2 2.7,5.3 1,7.8a894.9,894.9 0,0 0,-113.2 328.3l0,0.1zM771.6,839a72.2,72.2 0,1 1,-72.2 -71.9,71.9 71.9,0 0,1 72.2,71.9zM827.2,802a38.9,38.9 0,1 1,38.9 -38.7,39.1 39.1,0 0,1 -39,38.9l0.1,-0.1zM947.2,171.6L765.7,353.3c0,2.9 -1,3.9 -1,6.8 41,69.9 40,150.6 -19.5,212.7a4.7,4.7 0,0 1,-6.8 0L450.6,285.3a4.7,4.7 0,0 1,0 -6.8c62.4,-59.2 143.4,-59.2 213.7,-19.4 2.3,0.1 4.6,-0.2 6.8,-1l182.5,-180.6a66.4,66.4 0,1 1,93.7 94.2z" />
|
||||
</vector>
|
||||
12
app/src/main/res/drawable/ic_favorite_red.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:tint="#EF5350"
|
||||
android:viewportWidth="24.0"
|
||||
android:viewportHeight="24.0">
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M13.35,20.13c-0.76,0.69 -1.93,0.69 -2.69,-0.01l-0.11,-0.1C5.3,15.27 1.87,12.16 2,8.28c0.06,-1.7 0.93,-3.33 2.34,-4.29 2.64,-1.8 5.9,-0.96 7.66,1.1 1.76,-2.06 5.02,-2.91 7.66,-1.1 1.41,0.96 2.28,2.59 2.34,4.29 0.14,3.88 -3.3,6.99 -8.55,11.76l-0.1,0.09z" />
|
||||
</vector>
|
||||
|
||||
170
app/src/main/res/drawable/ic_launcher_background.xml
Normal file
@@ -0,0 +1,170 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path
|
||||
android:fillColor="#3DDC84"
|
||||
android:pathData="M0,0h108v108h-108z" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M9,0L9,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,0L19,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,0L29,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,0L39,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,0L49,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,0L59,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,0L69,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,0L79,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M89,0L89,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M99,0L99,108"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,9L108,9"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,19L108,19"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,29L108,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,39L108,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,49L108,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,59L108,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,69L108,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,79L108,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,89L108,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M0,99L108,99"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,29L89,29"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,39L89,39"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,49L89,49"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,59L89,59"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,69L89,69"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M19,79L89,79"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M29,19L29,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M39,19L39,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M49,19L49,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M59,19L59,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M69,19L69,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
<path
|
||||
android:fillColor="#00000000"
|
||||
android:pathData="M79,19L79,89"
|
||||
android:strokeWidth="0.8"
|
||||
android:strokeColor="#33FFFFFF" />
|
||||
</vector>
|
||||
30
app/src/main/res/drawable/ic_launcher_foreground.xml
Normal file
@@ -0,0 +1,30 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:aapt="http://schemas.android.com/aapt"
|
||||
android:width="108dp"
|
||||
android:height="108dp"
|
||||
android:viewportWidth="108"
|
||||
android:viewportHeight="108">
|
||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||
<aapt:attr name="android:fillColor">
|
||||
<gradient
|
||||
android:endX="85.84757"
|
||||
android:endY="92.4963"
|
||||
android:startX="42.9492"
|
||||
android:startY="49.59793"
|
||||
android:type="linear">
|
||||
<item
|
||||
android:color="#44000000"
|
||||
android:offset="0.0" />
|
||||
<item
|
||||
android:color="#00000000"
|
||||
android:offset="1.0" />
|
||||
</gradient>
|
||||
</aapt:attr>
|
||||
</path>
|
||||
<path
|
||||
android:fillColor="#FFFFFF"
|
||||
android:fillType="nonZero"
|
||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||
android:strokeWidth="1"
|
||||
android:strokeColor="#00000000" />
|
||||
</vector>
|
||||
9
app/src/main/res/drawable/ic_route.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="32dp"
|
||||
android:height="32dp"
|
||||
android:viewportWidth="1024"
|
||||
android:viewportHeight="1024">
|
||||
<path
|
||||
android:fillColor="#333333"
|
||||
android:pathData="M870.4,0a153.6,153.6 0,0 0,-153.6 153.6c0,133.6 153.6,307.2 153.6,307.2s153.6,-173.6 153.6,-307.2a153.6,153.6 0,0 0,-153.6 -153.6zM870.4,230.4A76.8,76.8 0,1 1,947.2 153.6,76.8 76.8,0 0,1 870.4,230.4zM256,256a256,256 0,0 0,-256 256c0,222.7 256,512 256,512s256,-289.3 256,-512a256,256 0,0 0,-256 -256zM256,640A128,128 0,1 1,384 512,128 128,0 0,1 256,640zM669.2,538.6a204.8,204.8 0,0 0,-13.3 81.4v14.8h51.2v-13.3a159.2,159.2 0,0 1,9.2 -61.4,129 129,0 0,1 5.6,-11.8l-45.1,-24.6q-4.1,6.7 -7.7,14.8zM713.7,475.6l34.3,37.9a174.1,174.1 0,0 1,79.4 -38.9l-11.3,-51.2a224.8,224.8 0,0 0,-102.4 52.2zM319.5,972.8l4.6,51.2c36.9,-3.1 71.7,-7.7 102.4,-12.8l-8.7,-51.2c-29.2,5.6 -63,9.7 -98.3,12.8zM606.7,892.9l-6.7,5.1 30.7,41 9.2,-7.2a194.6,194.6 0,0 0,59.9 -86l-48.6,-16.9a141.8,141.8 0,0 1,-44.5 64zM468,950.8l11.3,51.2a530.9,530.9 0,0 0,102.4 -33.3l-21,-47.1a487.4,487.4 0,0 1,-92.7 29.2zM658.9,687.1c0,20.5 3.1,41.5 3.1,62.5v35.3l51.2,5.1a403.5,403.5 0,0 0,0 -40.4c0,-22 0,-44.5 -3.1,-66z" />
|
||||
</vector>
|
||||
BIN
app/src/main/res/drawable/start.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
app/src/main/res/drawable/up.png
Normal file
|
After Width: | Height: | Size: 221 B |
91
app/src/main/res/layout/activity_main.xml
Normal file
@@ -0,0 +1,91 @@
|
||||
<?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:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".MainActivity">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="@color/white"
|
||||
android:paddingTop="8dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:paddingBottom="8dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_address"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="@drawable/et_bg"
|
||||
android:hint="请输入地址"
|
||||
android:imeOptions="actionSearch"
|
||||
android:paddingStart="12dp"
|
||||
android:singleLine="true"
|
||||
android:textColor="#000"
|
||||
android:textSize="14sp" />
|
||||
</com.google.android.material.appbar.MaterialToolbar>
|
||||
|
||||
<com.amap.api.maps.MapView
|
||||
android:id="@+id/map_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/toolbar" />
|
||||
|
||||
<!--浮动按钮-->
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab_poi"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="20dp"
|
||||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:src="@drawable/ic_favorite_red"
|
||||
app:hoveredFocusedTranslationZ="18dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:pressedTranslationZ="18dp" />
|
||||
|
||||
|
||||
<!--浮动按钮 清空marker-->
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab_clear_marker"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_above="@+id/fab_poi"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:clickable="true"
|
||||
android:src="@drawable/ic_clear"
|
||||
android:visibility="invisible"
|
||||
app:hoveredFocusedTranslationZ="18dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/fab_poi"
|
||||
app:layout_constraintEnd_toEndOf="@+id/fab_poi"
|
||||
app:pressedTranslationZ="18dp" />
|
||||
|
||||
<!--浮动按钮 跳转路线Activity-->
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/fab_route"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentBottom="true"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:layout_toLeftOf="@+id/fab_poi"
|
||||
android:clickable="true"
|
||||
android:src="@drawable/ic_route"
|
||||
app:backgroundTint="#FFF"
|
||||
app:backgroundTintMode="screen"
|
||||
app:fabSize="mini"
|
||||
app:hoveredFocusedTranslationZ="18dp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/fab_poi"
|
||||
app:layout_constraintEnd_toStartOf="@+id/fab_poi"
|
||||
app:pressedTranslationZ="18dp" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
154
app/src/main/res/layout/activity_route.xml
Normal file
@@ -0,0 +1,154 @@
|
||||
<?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:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".RouteActivity">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="16dp"
|
||||
android:text="出行方式:"
|
||||
android:textColor="#000"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/spinner"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<Spinner
|
||||
android:id="@+id/spinner"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_marginEnd="8dp"
|
||||
android:layout_weight="1"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_start"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="50dp"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:text="当前所在地"
|
||||
android:textColor="#000"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/spinner" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_start_address"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_toRightOf="@+id/tv_start"
|
||||
android:background="@null"
|
||||
android:padding="8dp"
|
||||
android:textColor="#000"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/tv_start"
|
||||
app:layout_constraintTop_toTopOf="@+id/tv_start" />
|
||||
|
||||
<View
|
||||
android:id="@+id/view"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0.5dp"
|
||||
android:layout_below="@+id/et_start_address"
|
||||
android:background="#000"
|
||||
app:layout_constraintTop_toBottomOf="@+id/et_start_address" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_end"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="50dp"
|
||||
android:layout_below="@+id/et_start_address"
|
||||
android:gravity="center_vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:text="前往目的地"
|
||||
android:textColor="#000"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/view" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_end_address"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="50dp"
|
||||
android:layout_below="@+id/et_start_address"
|
||||
android:layout_toRightOf="@+id/tv_end"
|
||||
android:background="@null"
|
||||
android:hint="请输入目的地"
|
||||
android:imeOptions="actionSearch"
|
||||
android:padding="8dp"
|
||||
android:singleLine="true"
|
||||
android:textColor="#000"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@+id/tv_end"
|
||||
app:layout_constraintTop_toBottomOf="@+id/tv_start" />
|
||||
|
||||
<View
|
||||
android:id="@+id/view2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0.5dp"
|
||||
android:layout_below="@+id/et_end_address"
|
||||
android:background="#000"
|
||||
app:layout_constraintTop_toBottomOf="@+id/et_end_address" />
|
||||
|
||||
|
||||
<!--地图-->
|
||||
<com.amap.api.maps.MapView
|
||||
android:id="@+id/map_view"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/view2" />
|
||||
|
||||
<!--地图路线规划详情布局-->
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/lay_bottom"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="60dp"
|
||||
android:background="@color/white"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_time"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginStart="16dp"
|
||||
android:layout_weight="1"
|
||||
android:singleLine="true"
|
||||
android:text="距离和时间"
|
||||
android:textColor="#333333"
|
||||
android:textSize="16sp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_detail"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_marginEnd="16dp"
|
||||
android:drawableEnd="@drawable/ic_blue_open"
|
||||
android:drawablePadding="4dp"
|
||||
android:gravity="center_vertical"
|
||||
android:text="详情"
|
||||
android:textColor="#4c90f9"
|
||||
android:textSize="14sp"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/tv_time"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/tv_time" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
51
app/src/main/res/layout/activity_route_detail.xml
Normal file
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout 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:id="@+id/main"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:background="#efefef"
|
||||
android:orientation="vertical"
|
||||
tools:context=".RouteDetailActivity">
|
||||
|
||||
<com.google.android.material.appbar.MaterialToolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="@color/white"
|
||||
app:navigationIcon="@drawable/ic_black_back"
|
||||
app:titleCentered="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/tv_time"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="70dp"
|
||||
android:layout_marginTop="2dp"
|
||||
android:background="#FFF"
|
||||
android:gravity="center_vertical"
|
||||
android:orientation="vertical"
|
||||
android:padding="5dp"
|
||||
android:paddingStart="12dp"
|
||||
android:textColor="#333333"
|
||||
android:textSize="16sp" />
|
||||
|
||||
|
||||
|
||||
<View
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="#e0e0e0" />
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/rv_route_detail"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:cacheColorHint="#00000000"
|
||||
android:divider="#00000000"
|
||||
android:fadingEdge="none"
|
||||
android:fadingEdgeLength="0dp"
|
||||
android:footerDividersEnabled="false"
|
||||
android:headerDividersEnabled="false"
|
||||
android:listSelector="#00000000" />
|
||||
</LinearLayout>
|
||||
41
app/src/main/res/layout/custom_info_contents.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<?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="horizontal" >
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/badge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="5dp"
|
||||
android:adjustViewBounds="true" >
|
||||
</ImageView>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textColor="#ff000000"
|
||||
android:textSize="14dp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/snippet"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textColor="#ff7f7f7f"
|
||||
android:textSize="14dp" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
41
app/src/main/res/layout/custom_info_window.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="100dp"
|
||||
android:layout_height="100dp"
|
||||
android:background="@mipmap/custom_info_bubble"
|
||||
android:orientation="horizontal" >
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/badge"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginRight="5dp" >
|
||||
</ImageView>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textColor="#ff000000"
|
||||
android:textSize="14dp"
|
||||
android:textStyle="bold" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/snippet"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textColor="#ff7f7f7f"
|
||||
android:textSize="14dp" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
110
app/src/main/res/layout/item_segment.xml
Normal file
@@ -0,0 +1,110 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="#FFF" >
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bus_seg_split_line"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:layout_marginLeft="50dp"
|
||||
android:layout_marginStart="50dp"
|
||||
android:background="#e0e0e0"/>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/bus_route_direction"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="44dp"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_marginLeft="11dp"
|
||||
android:layout_marginStart="11dp" >
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bus_dir_icon"
|
||||
android:layout_width="22dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:src="@drawable/dir_start" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bus_dir_icon_up"
|
||||
android:layout_width="2dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_above="@id/bus_dir_icon"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:background="#b6b6b6"
|
||||
android:visibility="gone"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bus_dir_icon_down"
|
||||
android:layout_width="2dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/bus_dir_icon"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:background="#b6b6b6"
|
||||
android:visibility="gone"/>
|
||||
</RelativeLayout>
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/bus_item"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="44dp" >
|
||||
|
||||
<RelativeLayout
|
||||
android:id="@+id/stationinfo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bus_expand_image"
|
||||
android:layout_width="25dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginEnd="6dp"
|
||||
android:layout_marginRight="6dp"
|
||||
android:clickable="true"
|
||||
android:scaleType="centerInside"
|
||||
android:src="@drawable/down"
|
||||
android:visibility="gone" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bus_station_num"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_toLeftOf="@id/bus_expand_image"
|
||||
android:layout_toStartOf="@id/bus_expand_image"
|
||||
android:gravity="center_vertical"
|
||||
android:textColor="#4c90f9"
|
||||
android:textSize="12sp"
|
||||
android:visibility="gone" >
|
||||
</TextView>
|
||||
</RelativeLayout>
|
||||
<TextView
|
||||
android:id="@+id/bus_line_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_marginLeft="50dp"
|
||||
android:layout_marginStart="50dp"
|
||||
android:layout_marginRight="70dp"
|
||||
android:layout_marginEnd="70dp"
|
||||
android:textColor="#333333"
|
||||
android:text="出发"
|
||||
android:textSize="14sp" />
|
||||
</RelativeLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/expand_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/bus_item"
|
||||
android:orientation="vertical">
|
||||
</LinearLayout>
|
||||
</RelativeLayout>
|
||||
47
app/src/main/res/layout/item_segment_ex.xml
Normal file
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="horizontal" >
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="27dp"
|
||||
android:layout_marginLeft="15.5dp"
|
||||
android:layout_marginStart="15.5dp" >
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bus_dir_icon"
|
||||
android:layout_width="13dp"
|
||||
android:layout_height="13dp"
|
||||
android:layout_centerVertical="true"
|
||||
android:src="@drawable/dir_station" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bus_dir_icon_up"
|
||||
android:layout_width="2dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_above="@id/bus_dir_icon"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:background="#b6b6b6" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/bus_dir_icon_down"
|
||||
android:layout_width="2dp"
|
||||
android:layout_height="match_parent"
|
||||
android:layout_below="@id/bus_dir_icon"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:background="#b6b6b6" />
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/bus_line_station_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:gravity="center_vertical"
|
||||
android:layout_marginLeft="20dp"
|
||||
android:layout_marginStart="20dp"
|
||||
android:textColor="#999999"
|
||||
android:textSize="13sp" />
|
||||
</LinearLayout>
|
||||
6
app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
6
app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@drawable/ic_launcher_background" />
|
||||
<foreground android:drawable="@drawable/ic_launcher_foreground" />
|
||||
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
|
||||
</adaptive-icon>
|
||||
BIN
app/src/main/res/mipmap-hdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 982 B |
BIN
app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 1.7 KiB |
BIN
app/src/main/res/mipmap-xhdpi/custom_info_bubble.9.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_my.png
Normal file
|
After Width: | Height: | Size: 777 KiB |
BIN
app/src/main/res/mipmap-xhdpi/ic_yuan.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
Normal file
|
After Width: | Height: | Size: 3.8 KiB |
BIN
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
Normal file
|
After Width: | Height: | Size: 7.6 KiB |
7
app/src/main/res/values-night/themes.xml
Normal file
@@ -0,0 +1,7 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Base.Theme.ManGoWalking" parent="Theme.Material3.DayNight.NoActionBar">
|
||||
<!-- Customize your dark theme here. -->
|
||||
<!-- <item name="colorPrimary">@color/my_dark_primary</item> -->
|
||||
</style>
|
||||
</resources>
|
||||
5
app/src/main/res/values/colors.xml
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<color name="black">#FF000000</color>
|
||||
<color name="white">#FFFFFFFF</color>
|
||||
</resources>
|
||||
3
app/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">ManGoWalking</string>
|
||||
</resources>
|
||||
9
app/src/main/res/values/themes.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<resources xmlns:tools="http://schemas.android.com/tools">
|
||||
<!-- Base application theme. -->
|
||||
<style name="Base.Theme.ManGoWalking" parent="Theme.Material3.DayNight.NoActionBar">
|
||||
<!-- Customize your light theme here. -->
|
||||
<!-- <item name="colorPrimary">@color/my_light_primary</item> -->
|
||||
</style>
|
||||
|
||||
<style name="Theme.ManGoWalking" parent="Base.Theme.ManGoWalking" />
|
||||
</resources>
|
||||