安卓應用開發學習:騰訊地圖SDK應用改進,實現定位、搜索、路線規劃功能集成

一、引言

我的上一篇學習日志《安卓應用開發學習:通過騰訊地圖SDK實現定位功能》記錄了利用騰訊地圖SDK實現手機定位功能,并能獲取地圖中心點的經緯度信息。這之后的幾天里,我對《Android??App 開發進階與項目實戰》一書第九章的內容深入解讀,看明白了其中關于地點搜索和路線規劃功能。原書中的這些功能都是分別做成不同的Activity,我則通過自己的努力嘗試,將這些功能都集成到一個Activity中(見下圖),在一些具體細節上,我花了一些心思,也收獲了不少開發經驗。

?

(路線規劃功能)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?(搜索功能)??

(之前就實現的定位功能)

二、新增的功能

1.界面調整

其實我很想照著專業的地圖軟件設計界面,奈何能力有限,只能保持之前的風格了,但由于增加了新的功能,如果把這些組件都顯示在頁面中,就沒法看了。因此,我在界面上做一些調整,首先是將界面頂部放置定位功能組件的區域改成了放置“出行”、“搜索”、“圖層”三個按鈕。分別對應路線規劃、搜索和定位三個功能模塊。這三個功能模塊則放置在了一個可隱藏的LinearLayout布局中,通過點擊不同的按鈕, 顯示不同的組件。

1.1 xml文件代碼

    <!-- ll_pop布局中包含的是出行、搜索、圖層按鈕對應的功能 --><!-- 出行、搜索、圖層三個組件的顯示互斥 --><LinearLayoutandroid:id="@+id/ll_pop"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="15dp"android:orientation="vertical"android:background="@drawable/radius_border_15"app:layout_constraintEnd_toEndOf="@id/mapView"app:layout_constraintStart_toStartOf="@id/mapView"app:layout_constraintTop_toTopOf="@id/mapView"><!-- 此RadioGroup組件對應出行按鈕 --><RadioGroupandroid:id="@+id/rg_travel"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="5dp"android:orientation="horizontal" ><RadioButtonandroid:id="@+id/rb_walk"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:checked="true"android:text="步行"android:textColor="@color/black"android:textSize="17sp" /><RadioButtonandroid:id="@+id/rb_drive"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:checked="false"android:text="駕車"android:textColor="@color/black"android:textSize="17sp" /><Buttonandroid:id="@+id/btn_start"android:layout_width="80dp"android:layout_height="wrap_content"android:text="出發"tools:ignore="ButtonStyle" /><Buttonandroid:id="@+id/btn_redo"android:layout_width="80dp"android:layout_marginStart="5dp"android:layout_marginEnd="5dp"android:layout_height="wrap_content"android:text="重來"tools:ignore="ButtonStyle" /></RadioGroup><!-- 以下的三個LinearLayout布局ll_search1、ll_search2、ll_search3對應搜索按鈕 --><LinearLayoutandroid:id="@+id/ll_search1"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="5dp"android:orientation="horizontal"><TextViewandroid:id="@+id/tv_searchType"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_marginStart="10dp"android:textColor="@color/black"android:textSize="16sp"android:text="搜索方式:" /><Spinnerandroid:id="@+id/sp_searchType"android:layout_width="wrap_content"android:layout_height="wrap_content"android:entries="@array/searchType" /><TextViewandroid:layout_width="wrap_content"android:layout_height="match_parent"android:gravity="center"android:text="在"android:textColor="@color/black"android:textSize="17sp" /><EditTextandroid:id="@+id/et_scope"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center"android:background="@drawable/editext_selector"android:textColor="@color/black"android:textSize="17sp"android:hint="  "android:autofillHints="范圍"android:inputType="none"/><TextViewandroid:id="@+id/tv_scope_desc"android:layout_width="wrap_content"android:layout_height="match_parent"android:gravity="center"android:layout_marginEnd="5dp"android:text="市內找"android:textColor="@color/black"android:textSize="17sp" /></LinearLayout><LinearLayoutandroid:id="@+id/ll_search2"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginStart="10dp"android:layout_marginEnd="10dp"android:orientation="horizontal"><SearchViewandroid:id="@+id/sv_searchPoi"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="@color/gray_245" /></LinearLayout><LinearLayoutandroid:id="@+id/ll_search3"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_horizontal"android:layout_marginBottom="5dp"android:orientation="horizontal"><Buttonandroid:id="@+id/btn_next_data"android:layout_width="100dp"android:layout_height="wrap_content"android:layout_marginEnd="5dp"android:text="下一組"tools:ignore="ButtonStyle" /><Buttonandroid:id="@+id/btn_clearMarked"android:layout_width="100dp"android:layout_marginStart="5dp"android:layout_height="wrap_content"android:text="清除標記"tools:ignore="ButtonStyle" /></LinearLayout><!-- 以下的ll_layer對應圖層按鈕 --><LinearLayoutandroid:id="@+id/ll_layer"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><RadioGroupandroid:id="@+id/rg_layer"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="5dp"android:layout_marginBottom="5dp"android:orientation="horizontal" ><RadioButtonandroid:id="@+id/rb_common"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:checked="true"android:text="普通"android:textColor="@color/black"android:textSize="17sp" /><RadioButtonandroid:id="@+id/rb_satellite"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:checked="false"android:text="衛星"android:textColor="@color/black"android:textSize="17sp" /><CheckBoxandroid:id="@+id/ck_traffic"android:layout_width="wrap_content"android:layout_height="wrap_content"android:checked="false"android:text="交通情況"android:textColor="@color/black"android:textSize="17sp" /><CheckBoxandroid:id="@+id/ck_centerPoint"android:layout_width="30dp"android:layout_height="wrap_content"android:layout_marginStart="10dp"android:checked="false"android:text=""android:textColor="@color/black"android:textSize="17sp" /><Buttonandroid:id="@+id/btn_getCenter"android:layout_width="78dp"android:layout_height="wrap_content"android:layout_marginEnd="5dp"android:text="中心點"/></RadioGroup></LinearLayout>

1.2 java文件中的邏輯代碼

點擊其中一個按鈕后,其對應的功能組件設置為顯示狀態,其它功能組件設置為隱藏狀態。

    @Overridepublic void onClick(View v) {ll_pop.setVisibility(View.INVISIBLE);if (v.getId() == R.id.btn_travel) {  // 出行按鈕if (isTravelPop) {ll_pop.setVisibility(View.INVISIBLE);} else {// 對出行、搜索、圖層功能的相關組件的顯示、隱藏進行設置ll_pop.setVisibility(View.VISIBLE);rg_travel.setVisibility(View.VISIBLE);ll_search1.setVisibility(View.GONE);ll_search2.setVisibility(View.GONE);ll_search3.setVisibility(View.GONE);ll_layer.setVisibility(View.GONE);travelModeOn = true;  // 出行模式開}isTravelPop = !isTravelPop;isSearchPop = false;isLayerPop = false;} else if (v.getId() == R.id.btn_search) {  // 搜索按鈕if (isSearchPop) {ll_pop.setVisibility(View.INVISIBLE);} else {// 對出行、搜索、圖層功能的相關組件的顯示、隱藏進行設置ll_pop.setVisibility(View.VISIBLE);rg_travel.setVisibility(View.GONE);ll_search1.setVisibility(View.VISIBLE);ll_search2.setVisibility(View.VISIBLE);ll_search3.setVisibility(View.VISIBLE);ll_layer.setVisibility(View.GONE);travelModeOn = false;  // 出行模式關,轉為搜索模式}isSearchPop = !isSearchPop;isTravelPop = false;isLayerPop = false;} else if (v.getId() == R.id.btn_layer) {  // 圖層按鈕if (isLayerPop) {ll_pop.setVisibility(View.INVISIBLE);} else {// 對出行、搜索、圖層功能的相關組件的顯示、隱藏進行設置ll_pop.setVisibility(View.VISIBLE);rg_travel.setVisibility(View.GONE);ll_search1.setVisibility(View.GONE);ll_search2.setVisibility(View.GONE);ll_search3.setVisibility(View.GONE);ll_layer.setVisibility(View.VISIBLE);}isLayerPop = !isLayerPop;isTravelPop = false;isSearchPop = false;}

2.增加的搜索功能

這個功能模塊是參照的書上第9章 9.3.3 小節開發的。主要功能有:

2.1 分兩種方式(搜城市、搜周邊)進行搜索。

?

????????????????????????(搜城市)? ? ????????????????????????????????????????????????? ? ? ? ? ? (搜周邊)

搜城市,可以任意指定一座城市,輸入關鍵字進行搜索;搜周邊著在手機定位附近進行搜索。

2.2選點、測距、生成閉合多邊形

在搜索模式下,點擊地圖上的非POI,會繪制一個紅色的點,再次點擊另外一處會生成第二個點,兩點間有連線,連線旁顯示兩點距離。

多次點擊,可以形成閉合多邊形。

?

2.3點擊POI(興趣點)顯示標識

這一功能是根據騰訊位置服務官網上的資料,由我自己添加的。點擊地圖上有名稱的地點,就會顯示一個標識。

2.4搜索功能有配額限制

這個模塊剛設計完成后進行搜索地點測試時,出現了“此Key每日調用量已打上限”的提示,導致搜索功能不能正常使用。

我在騰訊位置服務官網的“Android地圖SDK / 開發指南 / 檢索功能概述”頁面找到了答案。原來,Android地圖SDK提供的檢索能力依托于騰訊地圖開放平臺提供的 WebService API,所有的檢索接口都有配額限制。而我在添加Key的時候并沒有勾選WebService API。需要對key進行編輯,并分配額度。

(登錄自己的用戶進入我的應用,點key對應的編輯按鈕)

(勾選WebService API,默認選中域的白名單不用修改,點保存)

(進入賬戶額度頁面,給應用分配額度,將所有的項目都進行分配)

(分配了額度立即生效,再次運行搜索,能正常使用,且可以在調用統計中查看額度使用情況)

3.增加的出行功能

這個功能模塊是參照書上第9章 9.3.4 小節開發的。出行功能具有步行和駕車兩種模式。選好模式后,在地圖上選兩個點,會在兩點間顯示連線。點擊“出發”按鈕,軟件就會對出行軌跡進行動畫演示。

?

????????????????(步行模式)????????????????????????????????????????????????????????(駕車模式)????????

三、效果展示

演示動畫?

騰訊地圖SDK應用展示

四、關鍵代碼

最后把部分代碼貼出來。

1.activity文件

import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RadioGroup;
import android.widget.SearchView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;import com.bahamutjapp.util.MapTencentUtil;
import com.tencent.lbssearch.TencentSearch;
import com.tencent.lbssearch.httpresponse.BaseObject;
import com.tencent.lbssearch.httpresponse.HttpResponseListener;
import com.tencent.lbssearch.object.param.DrivingParam;
import com.tencent.lbssearch.object.param.SearchParam;
import com.tencent.lbssearch.object.param.WalkingParam;
import com.tencent.lbssearch.object.result.DrivingResultObject;
import com.tencent.lbssearch.object.result.SearchResultObject;
import com.tencent.lbssearch.object.result.WalkingResultObject;
import com.tencent.map.geolocation.TencentLocation;
import com.tencent.map.geolocation.TencentLocationListener;
import com.tencent.map.geolocation.TencentLocationManager;
import com.tencent.map.geolocation.TencentLocationRequest;
import com.tencent.tencentmap.mapsdk.maps.CameraUpdate;
import com.tencent.tencentmap.mapsdk.maps.CameraUpdateFactory;
import com.tencent.tencentmap.mapsdk.maps.MapView;
import com.tencent.tencentmap.mapsdk.maps.TencentMap;
import com.tencent.tencentmap.mapsdk.maps.UiSettings;
import com.tencent.tencentmap.mapsdk.maps.model.BitmapDescriptor;
import com.tencent.tencentmap.mapsdk.maps.model.BitmapDescriptorFactory;
import com.tencent.tencentmap.mapsdk.maps.model.CameraPosition;
import com.tencent.tencentmap.mapsdk.maps.model.LatLng;
import com.tencent.tencentmap.mapsdk.maps.model.LatLngBounds;
import com.tencent.tencentmap.mapsdk.maps.model.MapPoi;
import com.tencent.tencentmap.mapsdk.maps.model.Marker;
import com.tencent.tencentmap.mapsdk.maps.model.MarkerOptions;
import com.tencent.tencentmap.mapsdk.maps.model.PolygonOptions;
import com.tencent.tencentmap.mapsdk.maps.model.PolylineOptions;
import com.tencent.tencentmap.mapsdk.vector.utils.animation.MarkerTranslateAnimator;import java.util.ArrayList;
import java.util.List;public class MapNavigationActivity extends AppCompatActivity implements TencentLocationListener,TencentMap.OnMapClickListener, TencentMap.OnMapPoiClickListener, View.OnClickListener {private final static String TAG = "MapNavigationActivity";private TencentLocationManager mLocationManager; // 聲明一個騰訊定位管理器對象private MapView mMapView; // 聲明一個地圖視圖對象private TencentMap mTencentMap; // 聲明一個騰訊地圖對象private boolean isFirstLoc = true; // 是否首次定位private LatLng mMyLatLng;  // 我的位置private MarkerOptions mooMarker;  // 手機定位處的標記private MapPoi mSelectMapPoi;  // 選中的Poi// 出行功能private Boolean isTravelPop = false;private Boolean travelModeOn = false;  // 出行和搜索模式切換開關private RadioGroup rg_travel; // 出行方式單選按鈕組(同時也作為布局器)private final List<LatLng> mSaEPosList = new ArrayList<>(); // 起點和終點private final List<LatLng> mRouteList = new ArrayList<>(); // 導航路線列表// 搜索功能private Boolean isSearchPop = false;private TencentSearch mTencentSearch; // 搜索-聲明一個騰訊搜索對象private int mLoadIndex = 1; // 搜索-搜索結果的第幾頁private EditText et_scope; // 搜索-聲明一個編輯框對象private TextView tv_scope_desc; // 搜索-聲明一個文本視圖對象private SearchView sv_searchPoi;  // 搜索-搜索組件private int mSearchType;  // 下列選框選中項索引號private String mKeyWord = "";  // 獲取搜索框中的內容private final int SEARCH_CITY = 0; // 搜城市private final int SEARCH_NEARBY = 1; // 搜周邊// 圖層功能private Boolean isLayerPop = false;private Button btn_getCenter;  // 圖層-獲取中心點按鈕private TextView tv_centerPoint; // 圖層-中心點標記private LatLng mCenterLatLng;  // 地圖中心位置// 布局private LinearLayout ll_pop, ll_search1, ll_search2, ll_search3, ll_layer;  // 面板布局,搜索、圖層@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_map_navigation);initLocation(); // 初始化定位服務initView(); // 初始化視圖}// 初始化視圖private void initView() {// 出行、搜索、圖層菜單對應面板初始化ll_pop = findViewById(R.id.ll_pop);  // 包含出行、搜索、圖層功能的布局rg_travel = findViewById(R.id.rg_travel);  // 出行方式單選按鈕組(附帶布局功能)ll_search1 = findViewById(R.id.ll_search1);  // 搜索功能布局1ll_search2 = findViewById(R.id.ll_search2);  // 搜索功能布局2ll_search3 = findViewById(R.id.ll_search3);  // 搜索功能布局3ll_layer = findViewById(R.id.ll_layer);  // 圖層功能布局ll_pop.setVisibility(View.INVISIBLE);  // 將此布局設置為不可見// 中心點初始化tv_centerPoint = findViewById(R.id.tv_centerPoint);  // 中心點圖標tv_centerPoint.setVisibility(View.INVISIBLE);  // 中心點圖標不可見btn_getCenter = findViewById(R.id.btn_getCenter);  // 中心點按鈕btn_getCenter.setEnabled(false);  // 中心點按鈕不可用// 出行功能初始化rg_travel.setOnCheckedChangeListener((group, checkedId) -> showRoute());  // 出行方式監聽findViewById(R.id.btn_start).setOnClickListener(v -> {  // 出發按鈕if (mSaEPosList.size() < 2) {Toast.makeText(this, "請選中起點和終點后再出發", Toast.LENGTH_SHORT).show();} else {playDriveAnim();  // 播放行駛過程動畫}});findViewById(R.id.btn_redo).setOnClickListener(v -> {  // 重來按鈕mTencentMap.clearAllOverlays(); // 清除所有覆蓋物mSaEPosList.clear();  // 清除起點和終點位置mRouteList.clear();  // 清除路線showMyMarker(); // 顯示我的位置標記});// 搜索功能初始化mTencentSearch = new TencentSearch(this);  // 騰訊地圖搜索// 搜索-下拉列表框Spinner sp_searchType = findViewById(R.id.sp_searchType);  // 搜索方式下列選框sp_searchType.setSelection(0);  // 設置默認選擇項sp_searchType.setOnItemSelectedListener(new MethodSelectedListener());et_scope = findViewById(R.id.et_scope);  // 搜索范圍輸入框tv_scope_desc = findViewById(R.id.tv_scope_desc);  // 搜索范圍文本描述sv_searchPoi = findViewById(R.id.sv_searchPoi);  // 搜索框sv_searchPoi.setOnQueryTextListener(new SearchView.OnQueryTextListener() {// 當點擊搜索按鈕時觸發該方法@Overridepublic boolean onQueryTextSubmit(String s) {//Toast.makeText(this, "您選擇的是:" + s, Toast.LENGTH_SHORT).show();sv_searchPoi.clearFocus();  // 移除焦點mKeyWord = s;searchPoi();  // 搜索興趣點return false;}// 當搜索內容改變時觸發該方法@Overridepublic boolean onQueryTextChange(String s) {return false;}});findViewById(R.id.btn_next_data).setOnClickListener(v -> {  // 下一組按鈕mLoadIndex++;mTencentMap.clearAllOverlays(); // 清除所有覆蓋物mTencentMap.addMarker(mooMarker); // 往地圖添加手機定位標記searchPoi(); // 搜索指定的地點列表});findViewById(R.id.btn_clearMarked).setOnClickListener(v -> {  // 清除標記按鈕et_scope.setText("");  // 清除范圍文本輸入框內容sv_searchPoi.setQuery("", false);  // 清除搜索框內容mTencentMap.clearAllOverlays(); // 清除所有覆蓋物mPosList.clear();  // 清除標記點列表mSaEPosList.clear();  // 清除起點和終點列表mRouteList.clear();  // 清除路線列表isPolygon = false;mTencentMap.addMarker(mooMarker); // 往地圖添加手機定位標記});// 圖層功能初始化RadioGroup rg_layer = findViewById(R.id.rg_layer);  // 地圖類型單選按鈕組rg_layer.setOnCheckedChangeListener((group, checkedId) -> {if (checkedId == R.id.rb_common) {mTencentMap.setMapType(TencentMap.MAP_TYPE_NORMAL); // 設置普通地圖} else if (checkedId == R.id.rb_satellite) {mTencentMap.setMapType(TencentMap.MAP_TYPE_SATELLITE); // 設置衛星地圖}});CheckBox ck_traffic = findViewById(R.id.ck_traffic);  // 交通情況復選框ck_traffic.setOnCheckedChangeListener((buttonView, isChecked) -> {mTencentMap.setTrafficEnabled(isChecked); // 是否顯示交通擁堵狀況});CheckBox ck_centerPoint = findViewById(R.id.ck_centerPoint);  // 中心點復選框ck_centerPoint.setOnCheckedChangeListener((buttonView, isChecked) -> {if (isChecked) {tv_centerPoint.setVisibility(View.VISIBLE);  // 顯示中心點圖標btn_getCenter.setEnabled(true);  // 中心點按鈕可用} else {tv_centerPoint.setVisibility(View.INVISIBLE);btn_getCenter.setEnabled(false);}});// 設置點擊監聽器findViewById(R.id.btn_travel).setOnClickListener(this);  // 出行按鈕findViewById(R.id.btn_search).setOnClickListener(this);  // 搜索按鈕findViewById(R.id.btn_layer).setOnClickListener(this);  // 圖層按鈕findViewById(R.id.tv_enlarge).setOnClickListener(this);  // 放大地圖findViewById(R.id.tv_narrow).setOnClickListener(this);  // 縮小地圖findViewById(R.id.img_btn_goMyPlace).setOnClickListener(this);  // 回到我的位置btn_getCenter.setOnClickListener(this);  // 獲取中心點}  // initView-end// 初始化定位服務private void initLocation() {mMapView = findViewById(R.id.mapView);mTencentMap = mMapView.getMap();  // 獲取騰訊地圖對象UiSettings mysetting = mTencentMap.getUiSettings();mysetting.setCompassEnabled(true);  // 開啟指南針mTencentMap.setOnMapClickListener(this);  // 設置地圖的點擊監聽器mTencentMap.setOnMapPoiClickListener(this);  // 設置地圖POI點擊監聽器mLocationManager = TencentLocationManager.getInstance(this);// 創建騰訊定位請求對象TencentLocationRequest request = TencentLocationRequest.create();request.setInterval(30000).setAllowGPS(true);request.setRequestLevel(TencentLocationRequest.REQUEST_LEVEL_ADMIN_AREA);mLocationManager.requestLocationUpdates(request, this); // 開始定位監聽}// 定位變更監聽@Overridepublic void onLocationChanged(TencentLocation location, int resultCode, String resultDesc) {if (resultCode == TencentLocation.ERROR_OK) { // 定位成功if (location != null && isFirstLoc) { // 首次定位isFirstLoc = false;// 創建一個經緯度對象mMyLatLng = new LatLng(location.getLatitude(), location.getLongitude());showMyMarker(); // 顯示我的位置標記}} else { // 定位失敗Log.d(TAG, "定位失敗,錯誤代碼為"+resultCode+",錯誤描述為"+resultDesc);}}@Overridepublic void onStatusUpdate(String s, int i, String s1) { }// 騰訊地圖生命周期方法@Overrideprotected void onStart() {super.onStart();mMapView.onStart();}@Overrideprotected void onStop() {super.onStop();mMapView.onStop();}@Overridepublic void onPause() {super.onPause();mMapView.onPause();}@Overridepublic void onResume() {super.onResume();mMapView.onResume();}@Overrideprotected void onDestroy() {super.onDestroy();mLocationManager.removeUpdates(this); // 移除定位監聽mMapView.onDestroy();}// 顯示我的位置標記private void showMyMarker() {CameraUpdate update = CameraUpdateFactory.newLatLngZoom(mMyLatLng, 12);mTencentMap.moveCamera(update); // 把相機視角移動到指定地點showPosMarker(mMyLatLng, R.drawable.ic_my_location_32, "這是您的當前位置"); // 顯示位置標記}// 顯示位置標記private void showPosMarker(LatLng latLng, int imageId, String desc) {// 從指定圖片中獲取位圖描述BitmapDescriptor bitmapDesc = BitmapDescriptorFactory.fromResource(imageId);mooMarker = new MarkerOptions(latLng).draggable(false) // 不可拖動.visible(true).icon(bitmapDesc).title("手機定位").snippet(desc);mTencentMap.addMarker(mooMarker); // 往地圖添加手機定位標記}// 出行功能private Marker mCarMarker; // 聲明一個小車標記// 播放行駛過程動畫private void playDriveAnim() {if (mSaEPosList.size() < 2) {return;}if (mCarMarker != null) {mCarMarker.remove(); // 移除小車標記}int imageId;if (rg_travel.getCheckedRadioButtonId() == R.id.rb_walk) {imageId = R.drawable.icon_locate; // 步行} else {imageId = R.drawable.car; // 駕車}// 從指定圖片中獲取位圖描述BitmapDescriptor bitmapDesc = BitmapDescriptorFactory.fromResource(imageId);MarkerOptions ooMarker = new MarkerOptions(mRouteList.get(0)).anchor(0.5f, 0.5f).icon(bitmapDesc).flat(true).clockwise(false);mCarMarker = mTencentMap.addMarker(ooMarker); // 往地圖添加標記LatLng[] routeArray = mRouteList.toArray(new LatLng[0]);// 創建平移動畫MarkerTranslateAnimator anim = new MarkerTranslateAnimator(mCarMarker, 50 * 1000, routeArray, true);// 動態調整相機視角mTencentMap.animateCamera(CameraUpdateFactory.newLatLngBounds(LatLngBounds.builder().include(mRouteList).build(), 50));anim.startAnimation(); // 開始播放動畫}// 出行功能-展示導航路線private void showRoute() {if (mSaEPosList.size() >= 2) {mRouteList.clear();LatLng beginPos = mSaEPosList.get(0); // 獲取起點LatLng endPos = mSaEPosList.get(mSaEPosList.size()-1); // 獲取終點mTencentMap.clearAllOverlays(); // 清除所有覆蓋物mTencentMap.addMarker(mooMarker); // 往地圖添加手機定位標記showPosMarker(beginPos, R.drawable.icon_geo, "起點"); // 顯示位置標記showPosMarker(endPos, R.drawable.icon_geo, "終點"); // 顯示位置標記if (rg_travel.getCheckedRadioButtonId() == R.id.rb_walk) {getWalkingRoute(beginPos, endPos); // 規劃步行導航} else {getDrivingRoute(beginPos, endPos); // 規劃行車導航}}}// 出行功能-規劃步行導航private void getWalkingRoute(LatLng beginPos, LatLng endPos) {WalkingParam walkingParam = new WalkingParam();walkingParam.from(beginPos); // 指定步行的起點walkingParam.to(endPos); // 指定步行的終點// 創建一個騰訊搜索對象TencentSearch tencentSearch = new TencentSearch(getApplicationContext());Log.d(TAG, "checkParams:" + walkingParam.checkParams());// 根據步行參數規劃導航路線tencentSearch.getRoutePlan(walkingParam, new HttpResponseListener<WalkingResultObject>() {@Overridepublic void onSuccess(int statusCode, WalkingResultObject object) {if (object==null || object.result==null || object.result.routes==null) {Log.d(TAG, "導航路線為空");return;}Log.d(TAG, "message:" + object.message);for (WalkingResultObject.Route result : object.result.routes) {mRouteList.addAll(result.polyline);// 往地圖上添加一組連線mTencentMap.addPolyline(new PolylineOptions().addAll(mRouteList).color(0x880000ff).width(20));}}@Overridepublic void onFailure(int statusCode, String responseString, Throwable throwable) {Log.d(TAG, statusCode + "  " + responseString);}});}// 出行功能-規劃行車導航private void getDrivingRoute(LatLng beginPos, LatLng endPos) {// 創建導航參數DrivingParam drivingParam = new DrivingParam(beginPos, endPos);// 指定道路類型為主路drivingParam.roadType(DrivingParam.RoadType.ON_MAIN_ROAD);  // 道路類型-主路drivingParam.heading(90); // 起點位置的車頭方向drivingParam.accuracy(5); // 行車導航的精度,單位米// 創建一個騰訊搜索對象TencentSearch tencentSearch = new TencentSearch(this);// 根據行車參數規劃導航路線tencentSearch.getRoutePlan(drivingParam, new HttpResponseListener<DrivingResultObject>() {@Overridepublic void onSuccess(int statusCode, DrivingResultObject object) {if (object==null || object.result==null || object.result.routes==null) {Log.d(TAG, "導航路線為空");return;}Log.d(TAG, "message:" + object.message);for (DrivingResultObject.Route route : object.result.routes){mRouteList.addAll(route.polyline);// 往地圖上添加一組連線mTencentMap.addPolyline(new PolylineOptions().addAll(mRouteList).color(0x880000ff).width(20));}}@Overridepublic void onFailure(int statusCode, String responseString, Throwable throwable) {Log.d(TAG, statusCode + "  " + responseString);}});}// 搜索功能-搜索方式下列選框選擇監聽器class MethodSelectedListener implements AdapterView.OnItemSelectedListener {public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {mSearchType = arg2;if (mSearchType == SEARCH_CITY) {tv_scope_desc.setText("市內找");} else if (mSearchType == SEARCH_NEARBY) {tv_scope_desc.setText("米內找");}et_scope.setText("");sv_searchPoi.setQuery("", false);  // 清除搜索框內容}public void onNothingSelected(AdapterView<?> arg0) {}}// 搜索功能-搜索指定的地點列表public void searchPoi() {Log.d(TAG, "et_scope=" + et_scope.getText().toString()+ ", SearchKey=" + mKeyWord+ ", mLoadIndex=" + mLoadIndex);String scope = et_scope.getText().toString();  // 獲取輸入的范圍// 測試時發現scope為空時附近查詢會閃退,需要對scope進行發現bug,如果,就會導致程序閃退,需要添加判斷語句if (TextUtils.isEmpty(scope)) {Toast.makeText(this, "搜索的范圍為空", Toast.LENGTH_SHORT).show();return;}SearchParam searchParam = new SearchParam();if (mSearchType == SEARCH_CITY) { // 城市搜索SearchParam.Region region = new SearchParam.Region(scope) // 設置搜索城市.autoExtend(false); // 設置搜索范圍不擴大searchParam = new SearchParam(mKeyWord, region); // 構建地點檢索} else if (mSearchType == SEARCH_NEARBY) { // 周邊搜索int radius;try {radius = Integer.parseInt(scope);  // scope必須是有效值,否則不使用try會閃退} catch (Exception e){e.printStackTrace();Toast.makeText(this, "搜索范圍不是有效數字", Toast.LENGTH_SHORT).show();return;}SearchParam.Nearby nearby = new SearchParam.Nearby(mMyLatLng, radius).autoExtend(false); // 不擴大搜索范圍searchParam = new SearchParam(mKeyWord, nearby); // 構建地點檢索}searchParam.pageSize(10); // 每頁大小searchParam.pageIndex(mLoadIndex); // 第幾頁// 根據搜索參數查找符合條件的地點列表mTencentSearch.search(searchParam, new HttpResponseListener<BaseObject>() {@Overridepublic void onFailure(int arg0, String arg2, Throwable arg3) {Toast.makeText(getApplicationContext(), arg2, Toast.LENGTH_LONG).show();}@Overridepublic void onSuccess(int arg0, BaseObject arg1) {  // 搜索成功if (arg1 == null) {return;}SearchResultObject obj = (SearchResultObject) arg1;if(obj.data==null || obj.data.size()==0){return;}// 將地圖中心坐標移動到檢索到的第一個地點CameraUpdate update = CameraUpdateFactory.newLatLngZoom(obj.data.get(0).latLng, 12);mTencentMap.moveCamera(update); // 把相機視角移動到指定地點// 將其他檢索到的地點在地圖上用 marker 標出來for (SearchResultObject.SearchResultData data : obj.data){Log.d(TAG,"title:"+data.title + ";" + data.address);// 往地圖添加標記mTencentMap.addMarker(new MarkerOptions(data.latLng).title(data.title).snippet(data.address));}}});}// 下面是繪圖代碼// 功能:在地圖上點擊后,會添加一個點,再次點擊,添加第二個點,在兩點間添加連線,并顯示兩點距離,以此類推// 通過“清除標記”按鈕,可將添加的點和連線清除private final int lineColor = 0x55FF0000;  // 紅色-線段顏色private final int textColor = 0x990000FF;  // 藍色-字體顏色private final int polygonColor = 0x77FFFF00;  // 黃色-多邊形底色private final int radiusLimit = 100;  // 當前點與第一個點的距離限定private final List<LatLng> mPosList = new ArrayList<>();  // 創建列表,保存用戶在地圖上點擊的位置private boolean isPolygon = false;// 往地圖上添加一個點private void addDot(LatLng pos) {if (isPolygon) {mPosList.clear();isPolygon = false;}boolean isFirst = false;LatLng thisPos = pos;// 將當前點與第一個點和前一個點進行比較if (mPosList.size() > 0) {LatLng firstPos = mPosList.get(0);int distance = (int) Math.round(MapTencentUtil.getShortDistance(thisPos.longitude, thisPos.latitude,firstPos.longitude, firstPos.latitude));  // 當前點與第一個點的距離if (mPosList.size() == 1 && distance <= 0) { // 多次點擊起點,要忽略之return;} else if (mPosList.size() > 1) {LatLng lastPos = mPosList.get(mPosList.size() - 1);int lastDistance = (int) Math.round(MapTencentUtil.getShortDistance(thisPos.longitude, thisPos.latitude,lastPos.longitude, lastPos.latitude));  // 當前點與前一個點的距離if (lastDistance <= 0) { // 重復響應當前位置的點擊,要忽略之return;}}if (distance < radiusLimit * 2) {  // 當前點與第一個點的距離小于限定值,形成閉環thisPos = firstPos;isFirst = true;}Log.d(TAG, "distance=" + distance + ", radiusLimit=" + radiusLimit + ", isFirst=" + isFirst);// 在當前點與前一個點間畫直線LatLng lastPos = mPosList.get(mPosList.size() - 1);List<LatLng> pointList = new ArrayList<>();pointList.add(lastPos);pointList.add(thisPos);PolylineOptions ooPolyline = new PolylineOptions().width(2).color(lineColor).addAll(pointList);// 計算兩點之間距離distance = (int) Math.round(MapTencentUtil.getShortDistance(thisPos.longitude, thisPos.latitude,lastPos.longitude, lastPos.latitude));String disText;if (distance > 1000) {disText = Math.round(distance * 10.0f / 1000) / 10d + "公里";} else {disText = distance + "米";}PolylineOptions.SegmentText segment = new PolylineOptions.SegmentText(0, 1, disText);PolylineOptions.Text text = new PolylineOptions.Text.Builder(segment).color(textColor).size(15).build();ooPolyline.text(text);mTencentMap.addPolyline(ooPolyline); // 往地圖上添加一組連線}if (!isFirst) {// 從指定圖片中獲取位圖描述BitmapDescriptor bitmapDesc = BitmapDescriptorFactory.fromResource(R.drawable.icon_geo);MarkerOptions ooMarker = new MarkerOptions(thisPos).draggable(false) // 不可拖動.visible(true).icon(bitmapDesc);mTencentMap.addMarker(ooMarker); // 往地圖添加標記// 設置地圖標記的點擊監聽器mTencentMap.setOnMarkerClickListener(marker -> {LatLng markPos = marker.getPosition();addDot(markPos); // 往地圖上添加一個點marker.showInfoWindow(); // 顯示標記的信息窗口return true;});} else {  // isFirst為真,mPosList中的點已形成閉環if (mPosList.size() < 3) { // 可能存在地圖與標記同時響應點擊事件的情況mPosList.clear();isPolygon = false;return;}// 畫多邊形PolygonOptions ooPolygon = new PolygonOptions().addAll(mPosList).strokeColor(0xFF00FF00).strokeWidth(3).fillColor(polygonColor);  // 多邊形為綠邊mTencentMap.addPolygon(ooPolygon); // 往地圖上添加多邊形isPolygon = true;}mPosList.add(thisPos);}// 地圖點擊響應@Overridepublic void onMapClick(LatLng latLng) {if (travelModeOn) {  // 出行模式if (mSaEPosList.size() < 2) {mSaEPosList.add(latLng);} else {mSaEPosList.set(mSaEPosList.size()-1, latLng);}if (mSaEPosList.size() == 1) {showPosMarker(latLng, R.drawable.icon_geo, "起點"); // 顯示位置標記}showRoute(); // 展示導航路線} else {  // 非出行模式(搜索模式)執行添加點操作addDot(latLng); // 往地圖上添加一個點Log.d(TAG, "當前點擊位置的經緯度:" + latLng.longitude + " ;" + latLng.altitude);}}// 點擊地圖上的POI響應@Overridepublic void onClicked(MapPoi mapPoi) {if (!travelModeOn) {Log.d(TAG, "選中的Poi為:" + mapPoi.name);Toast.makeText(this, mapPoi.name + "\n" + mapPoi.getLongitude() + ", "+ mapPoi.getLatitude(), Toast.LENGTH_SHORT).show();// 清除之前的標記mTencentMap.clearAllOverlays();mTencentMap.addMarker(mooMarker); // 往地圖添加手機定位標記mSelectMapPoi = mapPoi;// 從指定圖片中獲取位圖描述BitmapDescriptor bitmapDesc = BitmapDescriptorFactory.fromResource(R.drawable.icon_current);MarkerOptions ooMarker = new MarkerOptions(mSelectMapPoi.position).draggable(false) // 不可拖動.visible(true).icon(bitmapDesc);mTencentMap.addMarker(ooMarker); // 往地圖添加標記} else {addDot(mapPoi.position); // 往地圖上添加一個點}}@Overridepublic void onClick(View v) {ll_pop.setVisibility(View.INVISIBLE);if (v.getId() == R.id.btn_travel) {  // 出行按鈕if (isTravelPop) {ll_pop.setVisibility(View.INVISIBLE);} else {// 對出行、搜索、圖層功能的相關組件的顯示、隱藏進行設置ll_pop.setVisibility(View.VISIBLE);rg_travel.setVisibility(View.VISIBLE);ll_search1.setVisibility(View.GONE);ll_search2.setVisibility(View.GONE);ll_search3.setVisibility(View.GONE);ll_layer.setVisibility(View.GONE);travelModeOn = true;  // // 出行模式開}isTravelPop = !isTravelPop;isSearchPop = false;isLayerPop = false;} else if (v.getId() == R.id.btn_search) {  // 搜索按鈕if (isSearchPop) {ll_pop.setVisibility(View.INVISIBLE);} else {// 對出行、搜索、圖層功能的相關組件的顯示、隱藏進行設置ll_pop.setVisibility(View.VISIBLE);rg_travel.setVisibility(View.GONE);ll_search1.setVisibility(View.VISIBLE);ll_search2.setVisibility(View.VISIBLE);ll_search3.setVisibility(View.VISIBLE);ll_layer.setVisibility(View.GONE);travelModeOn = false;  // 出行模式關,轉為搜索模式}isSearchPop = !isSearchPop;isTravelPop = false;isLayerPop = false;} else if (v.getId() == R.id.btn_layer) {  // 圖層按鈕if (isLayerPop) {ll_pop.setVisibility(View.INVISIBLE);} else {// 對出行、搜索、圖層功能的相關組件的顯示、隱藏進行設置ll_pop.setVisibility(View.VISIBLE);rg_travel.setVisibility(View.GONE);ll_search1.setVisibility(View.GONE);ll_search2.setVisibility(View.GONE);ll_search3.setVisibility(View.GONE);ll_layer.setVisibility(View.VISIBLE);}isLayerPop = !isLayerPop;isTravelPop = false;isSearchPop = false;} else if (v.getId() == R.id.tv_enlarge) {  // 放大地圖mTencentMap.moveCamera(CameraUpdateFactory.zoomIn()); // 放大一級// Toast.makeText(this, "放大地圖", Toast.LENGTH_SHORT).show();} else if (v.getId() == R.id.tv_narrow) {  // 縮小地圖mTencentMap.moveCamera(CameraUpdateFactory.zoomOut()); // 縮小一級// Toast.makeText(this, "縮小地圖", Toast.LENGTH_SHORT).show();} else if (v.getId() == R.id.img_btn_goMyPlace) {  // 回到我的位置CameraUpdate update = CameraUpdateFactory.newLatLng(mMyLatLng);mTencentMap.moveCamera(update); // 把相機視角移動到指定地點// Toast.makeText(this, "回到我的位置", Toast.LENGTH_SHORT).show();} else if (v.getId() == R.id.btn_getCenter) {  // 獲取中心點坐標CameraPosition cameraPosition = mTencentMap.getCameraPosition();mCenterLatLng = cameraPosition.target;Toast.makeText(this, "中心點坐標:" + mCenterLatLng.latitude + ";" + mCenterLatLng.longitude, Toast.LENGTH_LONG).show();}}}

2. mxl文件

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"tools:context=".MapNavigationActivity"><LinearLayoutandroid:id="@+id/ll_toolBar"android:layout_width="match_parent"android:layout_height="45dp"android:layout_marginStart="5dp"android:layout_marginEnd="5dp"android:gravity="center_horizontal"android:orientation="horizontal"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toTopOf="parent"><Buttonandroid:id="@+id/btn_travel"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="出行"tools:ignore="ButtonStyle" /><Buttonandroid:id="@+id/btn_search"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="15dp"android:layout_marginEnd="15dp"android:text="搜索"tools:ignore="ButtonStyle" /><Buttonandroid:id="@+id/btn_layer"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="圖層"tools:ignore="ButtonStyle" /></LinearLayout><com.tencent.tencentmap.mapsdk.maps.MapViewandroid:id="@+id/mapView"android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="1"app:layout_constraintEnd_toEndOf="parent"app:layout_constraintStart_toStartOf="parent"app:layout_constraintTop_toBottomOf="@+id/ll_toolBar"><TextViewandroid:id="@+id/tv_centerPoint"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_gravity="center"android:gravity="center"android:text="+"android:textColor="@color/red"android:textSize="48sp" /></com.tencent.tencentmap.mapsdk.maps.MapView><LinearLayoutandroid:id="@+id/ll_zoom"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginEnd="20dp"android:layout_marginBottom="120dp"android:orientation="vertical"android:background="@drawable/radius_border_15"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintEnd_toEndOf="parent"><TextViewandroid:id="@+id/tv_enlarge"android:layout_width="50dp"android:layout_height="50dp"android:layout_gravity="center_horizontal"android:layout_marginTop="10dp"android:layout_marginBottom="5dp"android:gravity="center"android:text="+"android:textColor="@color/black"android:textSize="32sp"android:textStyle="bold" /><TextViewandroid:id="@+id/tv_narrow"android:layout_width="50dp"android:layout_height="50dp"android:layout_gravity="center_horizontal"android:layout_marginTop="5dp"android:layout_marginBottom="10dp"android:gravity="center"android:text="-"android:textColor="@color/black"android:textSize="32sp"android:textStyle="bold" /></LinearLayout><LinearLayoutandroid:id="@+id/ll_goMyPlace"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_marginStart="20dp"android:layout_marginBottom="55dp"android:orientation="horizontal"android:background="@drawable/radius_border_15"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintStart_toStartOf="parent"><ImageButtonandroid:id="@+id/img_btn_goMyPlace"android:layout_width="54dp"android:layout_height="54dp"android:backgroundTint="@color/white"android:src="@drawable/ic_go_my_place"tools:ignore="ContentDescription" /></LinearLayout><!-- ll_pop布局中包含的是出現、搜索、圖層按鈕對應的功能 --><!-- 顯示互斥布局rg_travel;ll_search1、sv_searchPoi、ll_search2;ll_layer --><LinearLayoutandroid:id="@+id/ll_pop"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="15dp"android:orientation="vertical"android:background="@drawable/radius_border_15"app:layout_constraintEnd_toEndOf="@id/mapView"app:layout_constraintStart_toStartOf="@id/mapView"app:layout_constraintTop_toTopOf="@id/mapView"><RadioGroupandroid:id="@+id/rg_travel"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="5dp"android:orientation="horizontal" ><RadioButtonandroid:id="@+id/rb_walk"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:checked="true"android:text="步行"android:textColor="@color/black"android:textSize="17sp" /><RadioButtonandroid:id="@+id/rb_drive"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:checked="false"android:text="駕車"android:textColor="@color/black"android:textSize="17sp" /><Buttonandroid:id="@+id/btn_start"android:layout_width="80dp"android:layout_height="wrap_content"android:text="出發"tools:ignore="ButtonStyle" /><Buttonandroid:id="@+id/btn_redo"android:layout_width="80dp"android:layout_marginStart="5dp"android:layout_marginEnd="5dp"android:layout_height="wrap_content"android:text="重來"tools:ignore="ButtonStyle" /></RadioGroup><LinearLayoutandroid:id="@+id/ll_search1"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="5dp"android:orientation="horizontal"><TextViewandroid:id="@+id/tv_searchType"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:layout_marginStart="10dp"android:textColor="@color/black"android:textSize="16sp"android:text="搜索方式:" /><Spinnerandroid:id="@+id/sp_searchType"android:layout_width="wrap_content"android:layout_height="wrap_content"android:entries="@array/searchType" /><TextViewandroid:layout_width="wrap_content"android:layout_height="match_parent"android:gravity="center"android:text="在"android:textColor="@color/black"android:textSize="17sp" /><EditTextandroid:id="@+id/et_scope"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:gravity="center"android:background="@drawable/editext_selector"android:textColor="@color/black"android:textSize="17sp"android:hint="  "android:autofillHints="范圍"android:inputType="none"/><TextViewandroid:id="@+id/tv_scope_desc"android:layout_width="wrap_content"android:layout_height="match_parent"android:gravity="center"android:layout_marginEnd="5dp"android:text="市內找"android:textColor="@color/black"android:textSize="17sp" /></LinearLayout><LinearLayoutandroid:id="@+id/ll_search2"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginStart="10dp"android:layout_marginEnd="10dp"android:orientation="horizontal"><SearchViewandroid:id="@+id/sv_searchPoi"android:layout_width="match_parent"android:layout_height="wrap_content"android:background="@color/gray_245" /></LinearLayout><LinearLayoutandroid:id="@+id/ll_search3"android:layout_width="match_parent"android:layout_height="wrap_content"android:gravity="center_horizontal"android:layout_marginBottom="5dp"android:orientation="horizontal"><Buttonandroid:id="@+id/btn_next_data"android:layout_width="100dp"android:layout_height="wrap_content"android:layout_marginEnd="5dp"android:text="下一組"tools:ignore="ButtonStyle" /><Buttonandroid:id="@+id/btn_clearMarked"android:layout_width="100dp"android:layout_marginStart="5dp"android:layout_height="wrap_content"android:text="清除標記"tools:ignore="ButtonStyle" /></LinearLayout><LinearLayoutandroid:id="@+id/ll_layer"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"><RadioGroupandroid:id="@+id/rg_layer"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="5dp"android:layout_marginBottom="5dp"android:orientation="horizontal" ><RadioButtonandroid:id="@+id/rb_common"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:checked="true"android:text="普通"android:textColor="@color/black"android:textSize="17sp" /><RadioButtonandroid:id="@+id/rb_satellite"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_weight="1"android:checked="false"android:text="衛星"android:textColor="@color/black"android:textSize="17sp" /><CheckBoxandroid:id="@+id/ck_traffic"android:layout_width="wrap_content"android:layout_height="wrap_content"android:checked="false"android:text="交通情況"android:textColor="@color/black"android:textSize="17sp" /><CheckBoxandroid:id="@+id/ck_centerPoint"android:layout_width="30dp"android:layout_height="wrap_content"android:layout_marginStart="10dp"android:checked="false"android:text=""android:textColor="@color/black"android:textSize="17sp" /><Buttonandroid:id="@+id/btn_getCenter"android:layout_width="78dp"android:layout_height="wrap_content"android:layout_marginEnd="5dp"android:text="中心點"/></RadioGroup></LinearLayout></LinearLayout></androidx.constraintlayout.widget.ConstraintLayout>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/43513.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/43513.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/43513.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【深度學習實戰(44)】Anchor based and Anchor free(無錨VS有錨)

1 anchor-based 深度學習目標檢測通常都被建模成對一些候選區域進行分類和回歸的問題。在單階段檢測器中&#xff0c;這些候選區域就是通過滑窗方式產生的 anchor&#xff1b;在兩階段檢測器中&#xff0c;候選區域是 RPN 生成的 proposal&#xff0c;但是 RPN 本身仍然是對滑窗…

leetcode--層數最深葉子節點的和

leetcode地址&#xff1a;層數最深葉子節點的和 給你一棵二叉樹的根節點 root &#xff0c;請你返回 層數最深的葉子節點的和 。 示例 1&#xff1a; 輸入&#xff1a;root [1,2,3,4,5,null,6,7,null,null,null,null,8] 輸出&#xff1a;15 示例 2&#xff1a; 輸入&#xff…

多點GRE over IPsecVPN模式下nhrp的調優

一、實驗目的 在多點GRE over IPsecVPN模式下對nhrp進行調優&#xff0c;在總部開啟重定向、在分支開啟shortcut 網絡拓撲&#xff1a; 二、基礎設置 &#xff08;一&#xff09;如圖所示配置接口地址和區域&#xff0c;連接PC的接口位于trust區域、連接路由器的接口位于unt…

qt5.15關于qradiobutton遇到的坑

前言 不知道是只有我遇到了&#xff0c;還是qt本身就存在這個bug 當將2個qradiobutton放入到一個布局內&#xff0c;然后進行來回切換&#xff0c;若無數據刷新的情況下&#xff0c;切換無異常&#xff0c;當窗體內有數據開始刷新了&#xff0c;則點擊其中一個qradiobutton&am…

語法糖:代碼中的甜品

人不走空 &#x1f308;個人主頁&#xff1a;人不走空 &#x1f496;系列專欄&#xff1a;算法專題 ?詩詞歌賦&#xff1a;斯是陋室&#xff0c;惟吾德馨 目錄 &#x1f308;個人主頁&#xff1a;人不走空 &#x1f496;系列專欄&#xff1a;算法專題 ?詩詞歌…

以太網電路相關功能說明

RJ45模塊用于PHY芯片之間的互連&#xff0c;如圖1所示&#xff0c;RJ45有兩種組合形式&#xff0c;一種是分立式&#xff0c;網口變壓器和RJ45連接座是分開的&#xff0c;另一種是網口變壓器和RJ45集成在一起。 圖1 RJ45兩種主要形式 接下來以分立式RJ45的百兆網電路做個說明&a…

基于springboot+vue養老院管理系統+lw+源碼+講解+調試+演示視頻

第3章 系統分析 用戶的需求以及與本系統相似的在市場上存在的其它系統可以作為系統分析中參考的資料&#xff0c;分析人員可以根據這些信息確定出本系統具備的功能&#xff0c;分析出本系統具備的性能等內容。 3.1可行性分析 盡管系統是根據用戶的要求進行制作&#xff0c;但…

Matlab基礎語法篇(上)

Matlab基礎語法&#xff08;上&#xff09; 一、基知&#xff08;一&#xff09;界面介紹&#xff08;二&#xff09;常用快捷鍵&#xff08;三&#xff09;常用指令&#xff08;四&#xff09;Matlab幫助系統 二、運算基礎&#xff08;一&#xff09;變量&#xff08;二&#…

車道線識別研究

想研究車道線識別的深度學習網絡… 目錄 1.車道線數據集匯總及研究1.1 CULane Datesets1.1.1 相關連接1.1.2 介紹 1.2 Tusimple1.3 LLAMAS1.4 APOLLOSCAPE 2.車道線檢測框架2.1 LaneNet&#xff1a;實時車道線檢測框架 1.車道線數據集匯總及研究 參考文檔&#xff1a; 1.車道線…

sysbench 搭建使用

1.下載地址&#xff1a; https://github.com/akopytov/sysbench/tree/0.5 2.安裝 #進入解壓目錄&#xff0c;并且創建安裝目錄&#xff1a; unzip sysbench-0.5.zip cd sysbench-0.5#安裝依賴包 yum -y install automake autoconf libtool mysql-devel#準備編譯 ./autogen.s…

【初階數據結構】深入解析隊列:探索底層邏輯

初階數據結構相關知識點可以通過點擊以下鏈接進行學習一起加油&#xff01;時間與空間復雜度的深度剖析深入解析順序表:探索底層邏輯深入解析單鏈表:探索底層邏輯深入解析帶頭雙向循環鏈表:探索底層邏輯深入解析棧:探索底層邏輯深入解析隊列:探索底層邏輯深入解析循環隊列:探索…

三、Python日志系統之監控郵件發送

import smtplib from email.mime.text import MIMEText import time import os import datetime from watchdog.observers import Observer from watchdog.events import FileSystemEventHandler# 郵件配置 SMTP_SERVER smtp.example.com SMTP_PORT 587 SMTP_USERNAME your_…

EXISTS、NOT EXISTS、IN和NOT IN辨析

文章目錄 概要EXISTSNOT EXISTSINNOT IN辨析 概要 EXISTS、NOT EXISTS、IN 和 NOT IN 是 SQL 中用于查詢時進行條件判斷的關鍵字&#xff0c;它們在功能上有相似之處&#xff0c;但使用場景和性能表現上有所不同。 EXISTS 1.用途&#xff1a;用于子查詢中&#xff0c;判斷子…

C++:cv.absdiff函數含義

在OpenCV庫中&#xff0c;absdiff函數是一個非常重要的圖像處理函數&#xff0c;其意義在于計算兩個輸入數組&#xff08;通常是圖像&#xff09;之間對應元素差的絕對值。這個函數在圖像處理和計算機視覺領域有著廣泛的應用&#xff0c;如圖像對比、運動檢測等。 函數的基本用…

python第三方庫【numpy.array】的使用(超詳細)

NumPy 是 Python 中用于科學計算的基礎庫之一&#xff0c;它提供了高性能的多維數組對象以及這些數組的操作。NumPy 的核心數據結構是 ndarray&#xff08;N-dimensional array&#xff0c;N維數組&#xff09;&#xff0c;它提供了一種高效的存儲和操作大型多維數組的方法。以…

熬了一晚上,我從零實現了 Transformer 模型,把代碼講給你聽

自從徹底搞懂Self_Attention機制之后&#xff0c;筆者對Transformer模型的理解直接從地下一層上升到大氣層&#xff0c;瞬間打通任督二脈。夜夜入睡之前&#xff0c;那句柔情百轉的"Attention is all you need"時常在耳畔環繞&#xff0c;情到深處不禁拍床叫好。于是…

客戶案例|某大型證券公司數據庫運維場景數據安全實踐

證券行業涉及股票、債券、基金等金融產品的發行、交易和監管&#xff0c;業務具有數據規模大、數據價值高、數據應用場景復雜的顯著特點&#xff0c;其中高速流轉的業務系統中含有海量的客戶個人信息、交易、行情、咨詢等高敏感高價值信息。由于證券期貨業務場景所具有的特殊性…

初中生物知識點總結(人教版)

第一章 認識生物 一、 生物的特征&#xff1a; 1&#xff0e; 生物的生活需要營養 2&#xff0e; 生物能進行呼吸 3&#xff0e; 生物能排出身體內產生的廢物 4&#xff0e; 生物能對外界的刺激做出反應 5&#xff0e; 生物能生長和繁殖 除病毒以外&#xff0c;生物都是由細胞構…

單例模式(大話設計模式)C/C++版本

單例模式 C 餓漢 /* HM hungry man 餓漢 */ #include <iostream> using namespace std; class Singleton { private:Singleton() { cout << "單例對象創建&#xff01;" << endl; };Singleton(const Singleton &);Singleton &operator(c…

C++:cv.contourArea()函數解析

cv::contourArea是OpenCV庫中用于計算輪廓面積的函數。該函數非常適用于圖像處理中的形狀分析、物體檢測等領域。以下是關于cv::contourArea的詳細介紹&#xff1a; 一、函數概述 cv::contourArea是OpenCV中用于計算封閉輪廓面積的函數。它接受一個輪廓作為輸入&#xff0c;并…