当前位置:   article > 正文

安卓应用开发学习:腾讯地图SDK应用改进,实现定位、搜索、路线规划功能集成_在安卓项目中如何使用腾讯地图获取附近位置信息

在安卓项目中如何使用腾讯地图获取附近位置信息

一、引言

我的上一篇学习日志《安卓应用开发学习:通过腾讯地图SDK实现定位功能》记录了利用腾讯地图SDK实现手机定位功能,并能获取地图中心点的经纬度信息。这之后的几天里,我对《Android  App 开发进阶与项目实战》一书第九章的内容深入解读,看明白了其中关于地点搜索和路线规划功能。原书中的这些功能都是分别做成不同的Activity,我则通过自己的努力尝试,将这些功能都集成到一个Activity中(见下图),在一些具体细节上,我花了一些心思,也收获了不少开发经验。

 

(路线规划功能)                                               (搜索功能)  

(之前就实现的定位功能)

二、新增的功能

1.界面调整

其实我很想照着专业的地图软件设计界面,奈何能力有限,只能保持之前的风格了,但由于增加了新的功能,如果把这些组件都显示在页面中,就没法看了。因此,我在界面上做一些调整,首先是将界面顶部放置定位功能组件的区域改成了放置“出行”、“搜索”、“图层”三个按钮。分别对应路线规划、搜索和定位三个功能模块。这三个功能模块则放置在了一个可隐藏的LinearLayout布局中,通过点击不同的按钮, 显示不同的组件。

1.1 xml文件代码

  1. <!-- ll_pop布局中包含的是出行、搜索、图层按钮对应的功能 -->
  2. <!-- 出行、搜索、图层三个组件的显示互斥 -->
  3. <LinearLayout
  4. android:id="@+id/ll_pop"
  5. android:layout_width="match_parent"
  6. android:layout_height="wrap_content"
  7. android:layout_marginTop="15dp"
  8. android:orientation="vertical"
  9. android:background="@drawable/radius_border_15"
  10. app:layout_constraintEnd_toEndOf="@id/mapView"
  11. app:layout_constraintStart_toStartOf="@id/mapView"
  12. app:layout_constraintTop_toTopOf="@id/mapView">
  13. <!-- 此RadioGroup组件对应出行按钮 -->
  14. <RadioGroup
  15. android:id="@+id/rg_travel"
  16. android:layout_width="match_parent"
  17. android:layout_height="wrap_content"
  18. android:layout_margin="5dp"
  19. android:orientation="horizontal" >
  20. <RadioButton
  21. android:id="@+id/rb_walk"
  22. android:layout_width="0dp"
  23. android:layout_height="wrap_content"
  24. android:layout_weight="1"
  25. android:checked="true"
  26. android:text="步行"
  27. android:textColor="@color/black"
  28. android:textSize="17sp" />
  29. <RadioButton
  30. android:id="@+id/rb_drive"
  31. android:layout_width="0dp"
  32. android:layout_height="wrap_content"
  33. android:layout_weight="1"
  34. android:checked="false"
  35. android:text="驾车"
  36. android:textColor="@color/black"
  37. android:textSize="17sp" />
  38. <Button
  39. android:id="@+id/btn_start"
  40. android:layout_width="80dp"
  41. android:layout_height="wrap_content"
  42. android:text="出发"
  43. tools:ignore="ButtonStyle" />
  44. <Button
  45. android:id="@+id/btn_redo"
  46. android:layout_width="80dp"
  47. android:layout_marginStart="5dp"
  48. android:layout_marginEnd="5dp"
  49. android:layout_height="wrap_content"
  50. android:text="重来"
  51. tools:ignore="ButtonStyle" />
  52. </RadioGroup>
  53. <!-- 以下的三个LinearLayout布局ll_search1、ll_search2、ll_search3对应搜索按钮 -->
  54. <LinearLayout
  55. android:id="@+id/ll_search1"
  56. android:layout_width="match_parent"
  57. android:layout_height="wrap_content"
  58. android:layout_margin="5dp"
  59. android:orientation="horizontal">
  60. <TextView
  61. android:id="@+id/tv_searchType"
  62. android:layout_width="wrap_content"
  63. android:layout_height="wrap_content"
  64. android:layout_gravity="center"
  65. android:layout_marginStart="10dp"
  66. android:textColor="@color/black"
  67. android:textSize="16sp"
  68. android:text="搜索方式:" />
  69. <Spinner
  70. android:id="@+id/sp_searchType"
  71. android:layout_width="wrap_content"
  72. android:layout_height="wrap_content"
  73. android:entries="@array/searchType" />
  74. <TextView
  75. android:layout_width="wrap_content"
  76. android:layout_height="match_parent"
  77. android:gravity="center"
  78. android:text="在"
  79. android:textColor="@color/black"
  80. android:textSize="17sp" />
  81. <EditText
  82. android:id="@+id/et_scope"
  83. android:layout_width="0dp"
  84. android:layout_height="match_parent"
  85. android:layout_weight="1"
  86. android:gravity="center"
  87. android:background="@drawable/editext_selector"
  88. android:textColor="@color/black"
  89. android:textSize="17sp"
  90. android:hint=" "
  91. android:autofillHints="范围"
  92. android:inputType="none"/>
  93. <TextView
  94. android:id="@+id/tv_scope_desc"
  95. android:layout_width="wrap_content"
  96. android:layout_height="match_parent"
  97. android:gravity="center"
  98. android:layout_marginEnd="5dp"
  99. android:text="市内找"
  100. android:textColor="@color/black"
  101. android:textSize="17sp" />
  102. </LinearLayout>
  103. <LinearLayout
  104. android:id="@+id/ll_search2"
  105. android:layout_width="match_parent"
  106. android:layout_height="wrap_content"
  107. android:layout_marginStart="10dp"
  108. android:layout_marginEnd="10dp"
  109. android:orientation="horizontal">
  110. <SearchView
  111. android:id="@+id/sv_searchPoi"
  112. android:layout_width="match_parent"
  113. android:layout_height="wrap_content"
  114. android:background="@color/gray_245" />
  115. </LinearLayout>
  116. <LinearLayout
  117. android:id="@+id/ll_search3"
  118. android:layout_width="match_parent"
  119. android:layout_height="wrap_content"
  120. android:gravity="center_horizontal"
  121. android:layout_marginBottom="5dp"
  122. android:orientation="horizontal">
  123. <Button
  124. android:id="@+id/btn_next_data"
  125. android:layout_width="100dp"
  126. android:layout_height="wrap_content"
  127. android:layout_marginEnd="5dp"
  128. android:text="下一组"
  129. tools:ignore="ButtonStyle" />
  130. <Button
  131. android:id="@+id/btn_clearMarked"
  132. android:layout_width="100dp"
  133. android:layout_marginStart="5dp"
  134. android:layout_height="wrap_content"
  135. android:text="清除标记"
  136. tools:ignore="ButtonStyle" />
  137. </LinearLayout>
  138. <!-- 以下的ll_layer对应图层按钮 -->
  139. <LinearLayout
  140. android:id="@+id/ll_layer"
  141. android:layout_width="match_parent"
  142. android:layout_height="wrap_content"
  143. android:orientation="horizontal">
  144. <RadioGroup
  145. android:id="@+id/rg_layer"
  146. android:layout_width="match_parent"
  147. android:layout_height="wrap_content"
  148. android:layout_marginTop="5dp"
  149. android:layout_marginBottom="5dp"
  150. android:orientation="horizontal" >
  151. <RadioButton
  152. android:id="@+id/rb_common"
  153. android:layout_width="0dp"
  154. android:layout_height="wrap_content"
  155. android:layout_weight="1"
  156. android:checked="true"
  157. android:text="普通"
  158. android:textColor="@color/black"
  159. android:textSize="17sp" />
  160. <RadioButton
  161. android:id="@+id/rb_satellite"
  162. android:layout_width="0dp"
  163. android:layout_height="wrap_content"
  164. android:layout_weight="1"
  165. android:checked="false"
  166. android:text="卫星"
  167. android:textColor="@color/black"
  168. android:textSize="17sp" />
  169. <CheckBox
  170. android:id="@+id/ck_traffic"
  171. android:layout_width="wrap_content"
  172. android:layout_height="wrap_content"
  173. android:checked="false"
  174. android:text="交通情况"
  175. android:textColor="@color/black"
  176. android:textSize="17sp" />
  177. <CheckBox
  178. android:id="@+id/ck_centerPoint"
  179. android:layout_width="30dp"
  180. android:layout_height="wrap_content"
  181. android:layout_marginStart="10dp"
  182. android:checked="false"
  183. android:text=""
  184. android:textColor="@color/black"
  185. android:textSize="17sp" />
  186. <Button
  187. android:id="@+id/btn_getCenter"
  188. android:layout_width="78dp"
  189. android:layout_height="wrap_content"
  190. android:layout_marginEnd="5dp"
  191. android:text="中心点"/>
  192. </RadioGroup>
  193. </LinearLayout>

1.2 java文件中的逻辑代码

点击其中一个按钮后,其对应的功能组件设置为显示状态,其它功能组件设置为隐藏状态。

  1. @Override
  2. public void onClick(View v) {
  3. ll_pop.setVisibility(View.INVISIBLE);
  4. if (v.getId() == R.id.btn_travel) { // 出行按钮
  5. if (isTravelPop) {
  6. ll_pop.setVisibility(View.INVISIBLE);
  7. } else {
  8. // 对出行、搜索、图层功能的相关组件的显示、隐藏进行设置
  9. ll_pop.setVisibility(View.VISIBLE);
  10. rg_travel.setVisibility(View.VISIBLE);
  11. ll_search1.setVisibility(View.GONE);
  12. ll_search2.setVisibility(View.GONE);
  13. ll_search3.setVisibility(View.GONE);
  14. ll_layer.setVisibility(View.GONE);
  15. travelModeOn = true; // 出行模式开
  16. }
  17. isTravelPop = !isTravelPop;
  18. isSearchPop = false;
  19. isLayerPop = false;
  20. } else if (v.getId() == R.id.btn_search) { // 搜索按钮
  21. if (isSearchPop) {
  22. ll_pop.setVisibility(View.INVISIBLE);
  23. } else {
  24. // 对出行、搜索、图层功能的相关组件的显示、隐藏进行设置
  25. ll_pop.setVisibility(View.VISIBLE);
  26. rg_travel.setVisibility(View.GONE);
  27. ll_search1.setVisibility(View.VISIBLE);
  28. ll_search2.setVisibility(View.VISIBLE);
  29. ll_search3.setVisibility(View.VISIBLE);
  30. ll_layer.setVisibility(View.GONE);
  31. travelModeOn = false; // 出行模式关,转为搜索模式
  32. }
  33. isSearchPop = !isSearchPop;
  34. isTravelPop = false;
  35. isLayerPop = false;
  36. } else if (v.getId() == R.id.btn_layer) { // 图层按钮
  37. if (isLayerPop) {
  38. ll_pop.setVisibility(View.INVISIBLE);
  39. } else {
  40. // 对出行、搜索、图层功能的相关组件的显示、隐藏进行设置
  41. ll_pop.setVisibility(View.VISIBLE);
  42. rg_travel.setVisibility(View.GONE);
  43. ll_search1.setVisibility(View.GONE);
  44. ll_search2.setVisibility(View.GONE);
  45. ll_search3.setVisibility(View.GONE);
  46. ll_layer.setVisibility(View.VISIBLE);
  47. }
  48. isLayerPop = !isLayerPop;
  49. isTravelPop = false;
  50. isSearchPop = false;
  51. }

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文件

  1. import androidx.appcompat.app.AppCompatActivity;
  2. import android.os.Bundle;
  3. import android.text.TextUtils;
  4. import android.util.Log;
  5. import android.view.View;
  6. import android.widget.AdapterView;
  7. import android.widget.Button;
  8. import android.widget.CheckBox;
  9. import android.widget.EditText;
  10. import android.widget.LinearLayout;
  11. import android.widget.RadioGroup;
  12. import android.widget.SearchView;
  13. import android.widget.Spinner;
  14. import android.widget.TextView;
  15. import android.widget.Toast;
  16. import com.bahamutjapp.util.MapTencentUtil;
  17. import com.tencent.lbssearch.TencentSearch;
  18. import com.tencent.lbssearch.httpresponse.BaseObject;
  19. import com.tencent.lbssearch.httpresponse.HttpResponseListener;
  20. import com.tencent.lbssearch.object.param.DrivingParam;
  21. import com.tencent.lbssearch.object.param.SearchParam;
  22. import com.tencent.lbssearch.object.param.WalkingParam;
  23. import com.tencent.lbssearch.object.result.DrivingResultObject;
  24. import com.tencent.lbssearch.object.result.SearchResultObject;
  25. import com.tencent.lbssearch.object.result.WalkingResultObject;
  26. import com.tencent.map.geolocation.TencentLocation;
  27. import com.tencent.map.geolocation.TencentLocationListener;
  28. import com.tencent.map.geolocation.TencentLocationManager;
  29. import com.tencent.map.geolocation.TencentLocationRequest;
  30. import com.tencent.tencentmap.mapsdk.maps.CameraUpdate;
  31. import com.tencent.tencentmap.mapsdk.maps.CameraUpdateFactory;
  32. import com.tencent.tencentmap.mapsdk.maps.MapView;
  33. import com.tencent.tencentmap.mapsdk.maps.TencentMap;
  34. import com.tencent.tencentmap.mapsdk.maps.UiSettings;
  35. import com.tencent.tencentmap.mapsdk.maps.model.BitmapDescriptor;
  36. import com.tencent.tencentmap.mapsdk.maps.model.BitmapDescriptorFactory;
  37. import com.tencent.tencentmap.mapsdk.maps.model.CameraPosition;
  38. import com.tencent.tencentmap.mapsdk.maps.model.LatLng;
  39. import com.tencent.tencentmap.mapsdk.maps.model.LatLngBounds;
  40. import com.tencent.tencentmap.mapsdk.maps.model.MapPoi;
  41. import com.tencent.tencentmap.mapsdk.maps.model.Marker;
  42. import com.tencent.tencentmap.mapsdk.maps.model.MarkerOptions;
  43. import com.tencent.tencentmap.mapsdk.maps.model.PolygonOptions;
  44. import com.tencent.tencentmap.mapsdk.maps.model.PolylineOptions;
  45. import com.tencent.tencentmap.mapsdk.vector.utils.animation.MarkerTranslateAnimator;
  46. import java.util.ArrayList;
  47. import java.util.List;
  48. public class MapNavigationActivity extends AppCompatActivity implements TencentLocationListener,
  49. TencentMap.OnMapClickListener, TencentMap.OnMapPoiClickListener, View.OnClickListener {
  50. private final static String TAG = "MapNavigationActivity";
  51. private TencentLocationManager mLocationManager; // 声明一个腾讯定位管理器对象
  52. private MapView mMapView; // 声明一个地图视图对象
  53. private TencentMap mTencentMap; // 声明一个腾讯地图对象
  54. private boolean isFirstLoc = true; // 是否首次定位
  55. private LatLng mMyLatLng; // 我的位置
  56. private MarkerOptions mooMarker; // 手机定位处的标记
  57. private MapPoi mSelectMapPoi; // 选中的Poi
  58. // 出行功能
  59. private Boolean isTravelPop = false;
  60. private Boolean travelModeOn = false; // 出行和搜索模式切换开关
  61. private RadioGroup rg_travel; // 出行方式单选按钮组(同时也作为布局器)
  62. private final List<LatLng> mSaEPosList = new ArrayList<>(); // 起点和终点
  63. private final List<LatLng> mRouteList = new ArrayList<>(); // 导航路线列表
  64. // 搜索功能
  65. private Boolean isSearchPop = false;
  66. private TencentSearch mTencentSearch; // 搜索-声明一个腾讯搜索对象
  67. private int mLoadIndex = 1; // 搜索-搜索结果的第几页
  68. private EditText et_scope; // 搜索-声明一个编辑框对象
  69. private TextView tv_scope_desc; // 搜索-声明一个文本视图对象
  70. private SearchView sv_searchPoi; // 搜索-搜索组件
  71. private int mSearchType; // 下列选框选中项索引号
  72. private String mKeyWord = ""; // 获取搜索框中的内容
  73. private final int SEARCH_CITY = 0; // 搜城市
  74. private final int SEARCH_NEARBY = 1; // 搜周边
  75. // 图层功能
  76. private Boolean isLayerPop = false;
  77. private Button btn_getCenter; // 图层-获取中心点按钮
  78. private TextView tv_centerPoint; // 图层-中心点标记
  79. private LatLng mCenterLatLng; // 地图中心位置
  80. // 布局
  81. private LinearLayout ll_pop, ll_search1, ll_search2, ll_search3, ll_layer; // 面板布局,搜索、图层
  82. @Override
  83. protected void onCreate(Bundle savedInstanceState) {
  84. super.onCreate(savedInstanceState);
  85. setContentView(R.layout.activity_map_navigation);
  86. initLocation(); // 初始化定位服务
  87. initView(); // 初始化视图
  88. }
  89. // 初始化视图
  90. private void initView() {
  91. // 出行、搜索、图层菜单对应面板初始化
  92. ll_pop = findViewById(R.id.ll_pop); // 包含出行、搜索、图层功能的布局
  93. rg_travel = findViewById(R.id.rg_travel); // 出行方式单选按钮组(附带布局功能)
  94. ll_search1 = findViewById(R.id.ll_search1); // 搜索功能布局1
  95. ll_search2 = findViewById(R.id.ll_search2); // 搜索功能布局2
  96. ll_search3 = findViewById(R.id.ll_search3); // 搜索功能布局3
  97. ll_layer = findViewById(R.id.ll_layer); // 图层功能布局
  98. ll_pop.setVisibility(View.INVISIBLE); // 将此布局设置为不可见
  99. // 中心点初始化
  100. tv_centerPoint = findViewById(R.id.tv_centerPoint); // 中心点图标
  101. tv_centerPoint.setVisibility(View.INVISIBLE); // 中心点图标不可见
  102. btn_getCenter = findViewById(R.id.btn_getCenter); // 中心点按钮
  103. btn_getCenter.setEnabled(false); // 中心点按钮不可用
  104. // 出行功能初始化
  105. rg_travel.setOnCheckedChangeListener((group, checkedId) -> showRoute()); // 出行方式监听
  106. findViewById(R.id.btn_start).setOnClickListener(v -> { // 出发按钮
  107. if (mSaEPosList.size() < 2) {
  108. Toast.makeText(this, "请选中起点和终点后再出发", Toast.LENGTH_SHORT).show();
  109. } else {
  110. playDriveAnim(); // 播放行驶过程动画
  111. }
  112. });
  113. findViewById(R.id.btn_redo).setOnClickListener(v -> { // 重来按钮
  114. mTencentMap.clearAllOverlays(); // 清除所有覆盖物
  115. mSaEPosList.clear(); // 清除起点和终点位置
  116. mRouteList.clear(); // 清除路线
  117. showMyMarker(); // 显示我的位置标记
  118. });
  119. // 搜索功能初始化
  120. mTencentSearch = new TencentSearch(this); // 腾讯地图搜索
  121. // 搜索-下拉列表框
  122. Spinner sp_searchType = findViewById(R.id.sp_searchType); // 搜索方式下列选框
  123. sp_searchType.setSelection(0); // 设置默认选择项
  124. sp_searchType.setOnItemSelectedListener(new MethodSelectedListener());
  125. et_scope = findViewById(R.id.et_scope); // 搜索范围输入框
  126. tv_scope_desc = findViewById(R.id.tv_scope_desc); // 搜索范围文本描述
  127. sv_searchPoi = findViewById(R.id.sv_searchPoi); // 搜索框
  128. sv_searchPoi.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
  129. // 当点击搜索按钮时触发该方法
  130. @Override
  131. public boolean onQueryTextSubmit(String s) {
  132. //Toast.makeText(this, "您选择的是:" + s, Toast.LENGTH_SHORT).show();
  133. sv_searchPoi.clearFocus(); // 移除焦点
  134. mKeyWord = s;
  135. searchPoi(); // 搜索兴趣点
  136. return false;
  137. }
  138. // 当搜索内容改变时触发该方法
  139. @Override
  140. public boolean onQueryTextChange(String s) {
  141. return false;
  142. }
  143. });
  144. findViewById(R.id.btn_next_data).setOnClickListener(v -> { // 下一组按钮
  145. mLoadIndex++;
  146. mTencentMap.clearAllOverlays(); // 清除所有覆盖物
  147. mTencentMap.addMarker(mooMarker); // 往地图添加手机定位标记
  148. searchPoi(); // 搜索指定的地点列表
  149. });
  150. findViewById(R.id.btn_clearMarked).setOnClickListener(v -> { // 清除标记按钮
  151. et_scope.setText(""); // 清除范围文本输入框内容
  152. sv_searchPoi.setQuery("", false); // 清除搜索框内容
  153. mTencentMap.clearAllOverlays(); // 清除所有覆盖物
  154. mPosList.clear(); // 清除标记点列表
  155. mSaEPosList.clear(); // 清除起点和终点列表
  156. mRouteList.clear(); // 清除路线列表
  157. isPolygon = false;
  158. mTencentMap.addMarker(mooMarker); // 往地图添加手机定位标记
  159. });
  160. // 图层功能初始化
  161. RadioGroup rg_layer = findViewById(R.id.rg_layer); // 地图类型单选按钮组
  162. rg_layer.setOnCheckedChangeListener((group, checkedId) -> {
  163. if (checkedId == R.id.rb_common) {
  164. mTencentMap.setMapType(TencentMap.MAP_TYPE_NORMAL); // 设置普通地图
  165. } else if (checkedId == R.id.rb_satellite) {
  166. mTencentMap.setMapType(TencentMap.MAP_TYPE_SATELLITE); // 设置卫星地图
  167. }
  168. });
  169. CheckBox ck_traffic = findViewById(R.id.ck_traffic); // 交通情况复选框
  170. ck_traffic.setOnCheckedChangeListener((buttonView, isChecked) -> {
  171. mTencentMap.setTrafficEnabled(isChecked); // 是否显示交通拥堵状况
  172. });
  173. CheckBox ck_centerPoint = findViewById(R.id.ck_centerPoint); // 中心点复选框
  174. ck_centerPoint.setOnCheckedChangeListener((buttonView, isChecked) -> {
  175. if (isChecked) {
  176. tv_centerPoint.setVisibility(View.VISIBLE); // 显示中心点图标
  177. btn_getCenter.setEnabled(true); // 中心点按钮可用
  178. } else {
  179. tv_centerPoint.setVisibility(View.INVISIBLE);
  180. btn_getCenter.setEnabled(false);
  181. }
  182. });
  183. // 设置点击监听器
  184. findViewById(R.id.btn_travel).setOnClickListener(this); // 出行按钮
  185. findViewById(R.id.btn_search).setOnClickListener(this); // 搜索按钮
  186. findViewById(R.id.btn_layer).setOnClickListener(this); // 图层按钮
  187. findViewById(R.id.tv_enlarge).setOnClickListener(this); // 放大地图
  188. findViewById(R.id.tv_narrow).setOnClickListener(this); // 缩小地图
  189. findViewById(R.id.img_btn_goMyPlace).setOnClickListener(this); // 回到我的位置
  190. btn_getCenter.setOnClickListener(this); // 获取中心点
  191. } // initView-end
  192. // 初始化定位服务
  193. private void initLocation() {
  194. mMapView = findViewById(R.id.mapView);
  195. mTencentMap = mMapView.getMap(); // 获取腾讯地图对象
  196. UiSettings mysetting = mTencentMap.getUiSettings();
  197. mysetting.setCompassEnabled(true); // 开启指南针
  198. mTencentMap.setOnMapClickListener(this); // 设置地图的点击监听器
  199. mTencentMap.setOnMapPoiClickListener(this); // 设置地图POI点击监听器
  200. mLocationManager = TencentLocationManager.getInstance(this);
  201. // 创建腾讯定位请求对象
  202. TencentLocationRequest request = TencentLocationRequest.create();
  203. request.setInterval(30000).setAllowGPS(true);
  204. request.setRequestLevel(TencentLocationRequest.REQUEST_LEVEL_ADMIN_AREA);
  205. mLocationManager.requestLocationUpdates(request, this); // 开始定位监听
  206. }
  207. // 定位变更监听
  208. @Override
  209. public void onLocationChanged(TencentLocation location, int resultCode, String resultDesc) {
  210. if (resultCode == TencentLocation.ERROR_OK) { // 定位成功
  211. if (location != null && isFirstLoc) { // 首次定位
  212. isFirstLoc = false;
  213. // 创建一个经纬度对象
  214. mMyLatLng = new LatLng(location.getLatitude(), location.getLongitude());
  215. showMyMarker(); // 显示我的位置标记
  216. }
  217. } else { // 定位失败
  218. Log.d(TAG, "定位失败,错误代码为"+resultCode+",错误描述为"+resultDesc);
  219. }
  220. }
  221. @Override
  222. public void onStatusUpdate(String s, int i, String s1) { }
  223. // 腾讯地图生命周期方法
  224. @Override
  225. protected void onStart() {
  226. super.onStart();
  227. mMapView.onStart();
  228. }
  229. @Override
  230. protected void onStop() {
  231. super.onStop();
  232. mMapView.onStop();
  233. }
  234. @Override
  235. public void onPause() {
  236. super.onPause();
  237. mMapView.onPause();
  238. }
  239. @Override
  240. public void onResume() {
  241. super.onResume();
  242. mMapView.onResume();
  243. }
  244. @Override
  245. protected void onDestroy() {
  246. super.onDestroy();
  247. mLocationManager.removeUpdates(this); // 移除定位监听
  248. mMapView.onDestroy();
  249. }
  250. // 显示我的位置标记
  251. private void showMyMarker() {
  252. CameraUpdate update = CameraUpdateFactory.newLatLngZoom(mMyLatLng, 12);
  253. mTencentMap.moveCamera(update); // 把相机视角移动到指定地点
  254. showPosMarker(mMyLatLng, R.drawable.ic_my_location_32, "这是您的当前位置"); // 显示位置标记
  255. }
  256. // 显示位置标记
  257. private void showPosMarker(LatLng latLng, int imageId, String desc) {
  258. // 从指定图片中获取位图描述
  259. BitmapDescriptor bitmapDesc = BitmapDescriptorFactory.fromResource(imageId);
  260. mooMarker = new MarkerOptions(latLng).draggable(false) // 不可拖动
  261. .visible(true).icon(bitmapDesc).title("手机定位").snippet(desc);
  262. mTencentMap.addMarker(mooMarker); // 往地图添加手机定位标记
  263. }
  264. // 出行功能
  265. private Marker mCarMarker; // 声明一个小车标记
  266. // 播放行驶过程动画
  267. private void playDriveAnim() {
  268. if (mSaEPosList.size() < 2) {
  269. return;
  270. }
  271. if (mCarMarker != null) {
  272. mCarMarker.remove(); // 移除小车标记
  273. }
  274. int imageId;
  275. if (rg_travel.getCheckedRadioButtonId() == R.id.rb_walk) {
  276. imageId = R.drawable.icon_locate; // 步行
  277. } else {
  278. imageId = R.drawable.car; // 驾车
  279. }
  280. // 从指定图片中获取位图描述
  281. BitmapDescriptor bitmapDesc = BitmapDescriptorFactory.fromResource(imageId);
  282. MarkerOptions ooMarker = new MarkerOptions(mRouteList.get(0))
  283. .anchor(0.5f, 0.5f).icon(bitmapDesc).flat(true).clockwise(false);
  284. mCarMarker = mTencentMap.addMarker(ooMarker); // 往地图添加标记
  285. LatLng[] routeArray = mRouteList.toArray(new LatLng[0]);
  286. // 创建平移动画
  287. MarkerTranslateAnimator anim = new MarkerTranslateAnimator(mCarMarker, 50 * 1000, routeArray, true);
  288. // 动态调整相机视角
  289. mTencentMap.animateCamera(CameraUpdateFactory.newLatLngBounds(
  290. LatLngBounds.builder().include(mRouteList).build(), 50));
  291. anim.startAnimation(); // 开始播放动画
  292. }
  293. // 出行功能-展示导航路线
  294. private void showRoute() {
  295. if (mSaEPosList.size() >= 2) {
  296. mRouteList.clear();
  297. LatLng beginPos = mSaEPosList.get(0); // 获取起点
  298. LatLng endPos = mSaEPosList.get(mSaEPosList.size()-1); // 获取终点
  299. mTencentMap.clearAllOverlays(); // 清除所有覆盖物
  300. mTencentMap.addMarker(mooMarker); // 往地图添加手机定位标记
  301. showPosMarker(beginPos, R.drawable.icon_geo, "起点"); // 显示位置标记
  302. showPosMarker(endPos, R.drawable.icon_geo, "终点"); // 显示位置标记
  303. if (rg_travel.getCheckedRadioButtonId() == R.id.rb_walk) {
  304. getWalkingRoute(beginPos, endPos); // 规划步行导航
  305. } else {
  306. getDrivingRoute(beginPos, endPos); // 规划行车导航
  307. }
  308. }
  309. }
  310. // 出行功能-规划步行导航
  311. private void getWalkingRoute(LatLng beginPos, LatLng endPos) {
  312. WalkingParam walkingParam = new WalkingParam();
  313. walkingParam.from(beginPos); // 指定步行的起点
  314. walkingParam.to(endPos); // 指定步行的终点
  315. // 创建一个腾讯搜索对象
  316. TencentSearch tencentSearch = new TencentSearch(getApplicationContext());
  317. Log.d(TAG, "checkParams:" + walkingParam.checkParams());
  318. // 根据步行参数规划导航路线
  319. tencentSearch.getRoutePlan(walkingParam, new HttpResponseListener<WalkingResultObject>() {
  320. @Override
  321. public void onSuccess(int statusCode, WalkingResultObject object) {
  322. if (object==null || object.result==null || object.result.routes==null) {
  323. Log.d(TAG, "导航路线为空");
  324. return;
  325. }
  326. Log.d(TAG, "message:" + object.message);
  327. for (WalkingResultObject.Route result : object.result.routes) {
  328. mRouteList.addAll(result.polyline);
  329. // 往地图上添加一组连线
  330. mTencentMap.addPolyline(new PolylineOptions().addAll(mRouteList)
  331. .color(0x880000ff).width(20));
  332. }
  333. }
  334. @Override
  335. public void onFailure(int statusCode, String responseString, Throwable throwable) {
  336. Log.d(TAG, statusCode + " " + responseString);
  337. }
  338. });
  339. }
  340. // 出行功能-规划行车导航
  341. private void getDrivingRoute(LatLng beginPos, LatLng endPos) {
  342. // 创建导航参数
  343. DrivingParam drivingParam = new DrivingParam(beginPos, endPos);
  344. // 指定道路类型为主路
  345. drivingParam.roadType(DrivingParam.RoadType.ON_MAIN_ROAD); // 道路类型-主路
  346. drivingParam.heading(90); // 起点位置的车头方向
  347. drivingParam.accuracy(5); // 行车导航的精度,单位米
  348. // 创建一个腾讯搜索对象
  349. TencentSearch tencentSearch = new TencentSearch(this);
  350. // 根据行车参数规划导航路线
  351. tencentSearch.getRoutePlan(drivingParam, new HttpResponseListener<DrivingResultObject>() {
  352. @Override
  353. public void onSuccess(int statusCode, DrivingResultObject object) {
  354. if (object==null || object.result==null || object.result.routes==null) {
  355. Log.d(TAG, "导航路线为空");
  356. return;
  357. }
  358. Log.d(TAG, "message:" + object.message);
  359. for (DrivingResultObject.Route route : object.result.routes){
  360. mRouteList.addAll(route.polyline);
  361. // 往地图上添加一组连线
  362. mTencentMap.addPolyline(new PolylineOptions().addAll(mRouteList)
  363. .color(0x880000ff).width(20));
  364. }
  365. }
  366. @Override
  367. public void onFailure(int statusCode, String responseString, Throwable throwable) {
  368. Log.d(TAG, statusCode + " " + responseString);
  369. }
  370. });
  371. }
  372. // 搜索功能-搜索方式下列选框选择监听器
  373. class MethodSelectedListener implements AdapterView.OnItemSelectedListener {
  374. public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
  375. mSearchType = arg2;
  376. if (mSearchType == SEARCH_CITY) {
  377. tv_scope_desc.setText("市内找");
  378. } else if (mSearchType == SEARCH_NEARBY) {
  379. tv_scope_desc.setText("米内找");
  380. }
  381. et_scope.setText("");
  382. sv_searchPoi.setQuery("", false); // 清除搜索框内容
  383. }
  384. public void onNothingSelected(AdapterView<?> arg0) {}
  385. }
  386. // 搜索功能-搜索指定的地点列表
  387. public void searchPoi() {
  388. Log.d(TAG, "et_scope=" + et_scope.getText().toString()
  389. + ", SearchKey=" + mKeyWord
  390. + ", mLoadIndex=" + mLoadIndex);
  391. String scope = et_scope.getText().toString(); // 获取输入的范围
  392. // 测试时发现scope为空时附近查询会闪退,需要对scope进行发现bug,如果,就会导致程序闪退,需要添加判断语句
  393. if (TextUtils.isEmpty(scope)) {
  394. Toast.makeText(this, "搜索的范围为空", Toast.LENGTH_SHORT).show();
  395. return;
  396. }
  397. SearchParam searchParam = new SearchParam();
  398. if (mSearchType == SEARCH_CITY) { // 城市搜索
  399. SearchParam.Region region = new SearchParam
  400. .Region(scope) // 设置搜索城市
  401. .autoExtend(false); // 设置搜索范围不扩大
  402. searchParam = new SearchParam(mKeyWord, region); // 构建地点检索
  403. } else if (mSearchType == SEARCH_NEARBY) { // 周边搜索
  404. int radius;
  405. try {
  406. radius = Integer.parseInt(scope); // scope必须是有效值,否则不使用try会闪退
  407. } catch (Exception e){
  408. e.printStackTrace();
  409. Toast.makeText(this, "搜索范围不是有效数字", Toast.LENGTH_SHORT).show();
  410. return;
  411. }
  412. SearchParam.Nearby nearby = new SearchParam
  413. .Nearby(mMyLatLng, radius).autoExtend(false); // 不扩大搜索范围
  414. searchParam = new SearchParam(mKeyWord, nearby); // 构建地点检索
  415. }
  416. searchParam.pageSize(10); // 每页大小
  417. searchParam.pageIndex(mLoadIndex); // 第几页
  418. // 根据搜索参数查找符合条件的地点列表
  419. mTencentSearch.search(searchParam, new HttpResponseListener<BaseObject>() {
  420. @Override
  421. public void onFailure(int arg0, String arg2, Throwable arg3) {
  422. Toast.makeText(getApplicationContext(), arg2, Toast.LENGTH_LONG).show();
  423. }
  424. @Override
  425. public void onSuccess(int arg0, BaseObject arg1) { // 搜索成功
  426. if (arg1 == null) {
  427. return;
  428. }
  429. SearchResultObject obj = (SearchResultObject) arg1;
  430. if(obj.data==null || obj.data.size()==0){
  431. return;
  432. }
  433. // 将地图中心坐标移动到检索到的第一个地点
  434. CameraUpdate update = CameraUpdateFactory.newLatLngZoom(obj.data.get(0).latLng, 12);
  435. mTencentMap.moveCamera(update); // 把相机视角移动到指定地点
  436. // 将其他检索到的地点在地图上用 marker 标出来
  437. for (SearchResultObject.SearchResultData data : obj.data){
  438. Log.d(TAG,"title:"+data.title + ";" + data.address);
  439. // 往地图添加标记
  440. mTencentMap.addMarker(new MarkerOptions(data.latLng)
  441. .title(data.title).snippet(data.address));
  442. }
  443. }
  444. });
  445. }
  446. // 下面是绘图代码
  447. // 功能:在地图上点击后,会添加一个点,再次点击,添加第二个点,在两点间添加连线,并显示两点距离,以此类推
  448. // 通过“清除标记”按钮,可将添加的点和连线清除
  449. private final int lineColor = 0x55FF0000; // 红色-线段颜色
  450. private final int textColor = 0x990000FF; // 蓝色-字体颜色
  451. private final int polygonColor = 0x77FFFF00; // 黄色-多边形底色
  452. private final int radiusLimit = 100; // 当前点与第一个点的距离限定
  453. private final List<LatLng> mPosList = new ArrayList<>(); // 创建列表,保存用户在地图上点击的位置
  454. private boolean isPolygon = false;
  455. // 往地图上添加一个点
  456. private void addDot(LatLng pos) {
  457. if (isPolygon) {
  458. mPosList.clear();
  459. isPolygon = false;
  460. }
  461. boolean isFirst = false;
  462. LatLng thisPos = pos;
  463. // 将当前点与第一个点和前一个点进行比较
  464. if (mPosList.size() > 0) {
  465. LatLng firstPos = mPosList.get(0);
  466. int distance = (int) Math.round(MapTencentUtil.getShortDistance(
  467. thisPos.longitude, thisPos.latitude,
  468. firstPos.longitude, firstPos.latitude)); // 当前点与第一个点的距离
  469. if (mPosList.size() == 1 && distance <= 0) { // 多次点击起点,要忽略之
  470. return;
  471. } else if (mPosList.size() > 1) {
  472. LatLng lastPos = mPosList.get(mPosList.size() - 1);
  473. int lastDistance = (int) Math.round(MapTencentUtil.getShortDistance(
  474. thisPos.longitude, thisPos.latitude,
  475. lastPos.longitude, lastPos.latitude)); // 当前点与前一个点的距离
  476. if (lastDistance <= 0) { // 重复响应当前位置的点击,要忽略之
  477. return;
  478. }
  479. }
  480. if (distance < radiusLimit * 2) { // 当前点与第一个点的距离小于限定值,形成闭环
  481. thisPos = firstPos;
  482. isFirst = true;
  483. }
  484. Log.d(TAG, "distance=" + distance + ", radiusLimit=" + radiusLimit + ", isFirst=" + isFirst);
  485. // 在当前点与前一个点间画直线
  486. LatLng lastPos = mPosList.get(mPosList.size() - 1);
  487. List<LatLng> pointList = new ArrayList<>();
  488. pointList.add(lastPos);
  489. pointList.add(thisPos);
  490. PolylineOptions ooPolyline = new PolylineOptions().width(2)
  491. .color(lineColor).addAll(pointList);
  492. // 计算两点之间距离
  493. distance = (int) Math.round(MapTencentUtil.getShortDistance(
  494. thisPos.longitude, thisPos.latitude,
  495. lastPos.longitude, lastPos.latitude));
  496. String disText;
  497. if (distance > 1000) {
  498. disText = Math.round(distance * 10.0f / 1000) / 10d + "公里";
  499. } else {
  500. disText = distance + "米";
  501. }
  502. PolylineOptions.SegmentText segment = new PolylineOptions.SegmentText(0, 1, disText);
  503. PolylineOptions.Text text = new PolylineOptions.Text.Builder(segment)
  504. .color(textColor).size(15).build();
  505. ooPolyline.text(text);
  506. mTencentMap.addPolyline(ooPolyline); // 往地图上添加一组连线
  507. }
  508. if (!isFirst) {
  509. // 从指定图片中获取位图描述
  510. BitmapDescriptor bitmapDesc = BitmapDescriptorFactory.fromResource(R.drawable.icon_geo);
  511. MarkerOptions ooMarker = new MarkerOptions(thisPos).draggable(false) // 不可拖动
  512. .visible(true).icon(bitmapDesc);
  513. mTencentMap.addMarker(ooMarker); // 往地图添加标记
  514. // 设置地图标记的点击监听器
  515. mTencentMap.setOnMarkerClickListener(marker -> {
  516. LatLng markPos = marker.getPosition();
  517. addDot(markPos); // 往地图上添加一个点
  518. marker.showInfoWindow(); // 显示标记的信息窗口
  519. return true;
  520. });
  521. } else { // isFirst为真,mPosList中的点已形成闭环
  522. if (mPosList.size() < 3) { // 可能存在地图与标记同时响应点击事件的情况
  523. mPosList.clear();
  524. isPolygon = false;
  525. return;
  526. }
  527. // 画多边形
  528. PolygonOptions ooPolygon = new PolygonOptions().addAll(mPosList)
  529. .strokeColor(0xFF00FF00).strokeWidth(3)
  530. .fillColor(polygonColor); // 多边形为绿边
  531. mTencentMap.addPolygon(ooPolygon); // 往地图上添加多边形
  532. isPolygon = true;
  533. }
  534. mPosList.add(thisPos);
  535. }
  536. // 地图点击响应
  537. @Override
  538. public void onMapClick(LatLng latLng) {
  539. if (travelModeOn) { // 出行模式
  540. if (mSaEPosList.size() < 2) {
  541. mSaEPosList.add(latLng);
  542. } else {
  543. mSaEPosList.set(mSaEPosList.size()-1, latLng);
  544. }
  545. if (mSaEPosList.size() == 1) {
  546. showPosMarker(latLng, R.drawable.icon_geo, "起点"); // 显示位置标记
  547. }
  548. showRoute(); // 展示导航路线
  549. } else { // 非出行模式(搜索模式)执行添加点操作
  550. addDot(latLng); // 往地图上添加一个点
  551. Log.d(TAG, "当前点击位置的经纬度:" + latLng.longitude + " ;" + latLng.altitude);
  552. }
  553. }
  554. // 点击地图上的POI响应
  555. @Override
  556. public void onClicked(MapPoi mapPoi) {
  557. if (!travelModeOn) {
  558. Log.d(TAG, "选中的Poi为:" + mapPoi.name);
  559. Toast.makeText(this, mapPoi.name + "\n" + mapPoi.getLongitude() + ", "
  560. + mapPoi.getLatitude(), Toast.LENGTH_SHORT).show();
  561. // 清除之前的标记
  562. mTencentMap.clearAllOverlays();
  563. mTencentMap.addMarker(mooMarker); // 往地图添加手机定位标记
  564. mSelectMapPoi = mapPoi;
  565. // 从指定图片中获取位图描述
  566. BitmapDescriptor bitmapDesc = BitmapDescriptorFactory.fromResource(R.drawable.icon_current);
  567. MarkerOptions ooMarker = new MarkerOptions(mSelectMapPoi.position).draggable(false) // 不可拖动
  568. .visible(true).icon(bitmapDesc);
  569. mTencentMap.addMarker(ooMarker); // 往地图添加标记
  570. } else {
  571. addDot(mapPoi.position); // 往地图上添加一个点
  572. }
  573. }
  574. @Override
  575. public void onClick(View v) {
  576. ll_pop.setVisibility(View.INVISIBLE);
  577. if (v.getId() == R.id.btn_travel) { // 出行按钮
  578. if (isTravelPop) {
  579. ll_pop.setVisibility(View.INVISIBLE);
  580. } else {
  581. // 对出行、搜索、图层功能的相关组件的显示、隐藏进行设置
  582. ll_pop.setVisibility(View.VISIBLE);
  583. rg_travel.setVisibility(View.VISIBLE);
  584. ll_search1.setVisibility(View.GONE);
  585. ll_search2.setVisibility(View.GONE);
  586. ll_search3.setVisibility(View.GONE);
  587. ll_layer.setVisibility(View.GONE);
  588. travelModeOn = true; // // 出行模式开
  589. }
  590. isTravelPop = !isTravelPop;
  591. isSearchPop = false;
  592. isLayerPop = false;
  593. } else if (v.getId() == R.id.btn_search) { // 搜索按钮
  594. if (isSearchPop) {
  595. ll_pop.setVisibility(View.INVISIBLE);
  596. } else {
  597. // 对出行、搜索、图层功能的相关组件的显示、隐藏进行设置
  598. ll_pop.setVisibility(View.VISIBLE);
  599. rg_travel.setVisibility(View.GONE);
  600. ll_search1.setVisibility(View.VISIBLE);
  601. ll_search2.setVisibility(View.VISIBLE);
  602. ll_search3.setVisibility(View.VISIBLE);
  603. ll_layer.setVisibility(View.GONE);
  604. travelModeOn = false; // 出行模式关,转为搜索模式
  605. }
  606. isSearchPop = !isSearchPop;
  607. isTravelPop = false;
  608. isLayerPop = false;
  609. } else if (v.getId() == R.id.btn_layer) { // 图层按钮
  610. if (isLayerPop) {
  611. ll_pop.setVisibility(View.INVISIBLE);
  612. } else {
  613. // 对出行、搜索、图层功能的相关组件的显示、隐藏进行设置
  614. ll_pop.setVisibility(View.VISIBLE);
  615. rg_travel.setVisibility(View.GONE);
  616. ll_search1.setVisibility(View.GONE);
  617. ll_search2.setVisibility(View.GONE);
  618. ll_search3.setVisibility(View.GONE);
  619. ll_layer.setVisibility(View.VISIBLE);
  620. }
  621. isLayerPop = !isLayerPop;
  622. isTravelPop = false;
  623. isSearchPop = false;
  624. } else if (v.getId() == R.id.tv_enlarge) { // 放大地图
  625. mTencentMap.moveCamera(CameraUpdateFactory.zoomIn()); // 放大一级
  626. // Toast.makeText(this, "放大地图", Toast.LENGTH_SHORT).show();
  627. } else if (v.getId() == R.id.tv_narrow) { // 缩小地图
  628. mTencentMap.moveCamera(CameraUpdateFactory.zoomOut()); // 缩小一级
  629. // Toast.makeText(this, "缩小地图", Toast.LENGTH_SHORT).show();
  630. } else if (v.getId() == R.id.img_btn_goMyPlace) { // 回到我的位置
  631. CameraUpdate update = CameraUpdateFactory.newLatLng(mMyLatLng);
  632. mTencentMap.moveCamera(update); // 把相机视角移动到指定地点
  633. // Toast.makeText(this, "回到我的位置", Toast.LENGTH_SHORT).show();
  634. } else if (v.getId() == R.id.btn_getCenter) { // 获取中心点坐标
  635. CameraPosition cameraPosition = mTencentMap.getCameraPosition();
  636. mCenterLatLng = cameraPosition.target;
  637. Toast.makeText(this, "中心点坐标:" + mCenterLatLng.latitude + ";" + mCenterLatLng.longitude, Toast.LENGTH_LONG).show();
  638. }
  639. }
  640. }

2. mxl文件

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. xmlns:app="http://schemas.android.com/apk/res-auto"
  4. xmlns:tools="http://schemas.android.com/tools"
  5. android:layout_width="match_parent"
  6. android:layout_height="match_parent"
  7. tools:context=".MapNavigationActivity">
  8. <LinearLayout
  9. android:id="@+id/ll_toolBar"
  10. android:layout_width="match_parent"
  11. android:layout_height="45dp"
  12. android:layout_marginStart="5dp"
  13. android:layout_marginEnd="5dp"
  14. android:gravity="center_horizontal"
  15. android:orientation="horizontal"
  16. app:layout_constraintEnd_toEndOf="parent"
  17. app:layout_constraintStart_toStartOf="parent"
  18. app:layout_constraintTop_toTopOf="parent">
  19. <Button
  20. android:id="@+id/btn_travel"
  21. android:layout_width="wrap_content"
  22. android:layout_height="wrap_content"
  23. android:text="出行"
  24. tools:ignore="ButtonStyle" />
  25. <Button
  26. android:id="@+id/btn_search"
  27. android:layout_width="wrap_content"
  28. android:layout_height="wrap_content"
  29. android:layout_marginStart="15dp"
  30. android:layout_marginEnd="15dp"
  31. android:text="搜索"
  32. tools:ignore="ButtonStyle" />
  33. <Button
  34. android:id="@+id/btn_layer"
  35. android:layout_width="wrap_content"
  36. android:layout_height="wrap_content"
  37. android:text="图层"
  38. tools:ignore="ButtonStyle" />
  39. </LinearLayout>
  40. <com.tencent.tencentmap.mapsdk.maps.MapView
  41. android:id="@+id/mapView"
  42. android:layout_width="match_parent"
  43. android:layout_height="0dp"
  44. android:layout_weight="1"
  45. app:layout_constraintEnd_toEndOf="parent"
  46. app:layout_constraintStart_toStartOf="parent"
  47. app:layout_constraintTop_toBottomOf="@+id/ll_toolBar">
  48. <TextView
  49. android:id="@+id/tv_centerPoint"
  50. android:layout_width="match_parent"
  51. android:layout_height="match_parent"
  52. android:layout_gravity="center"
  53. android:gravity="center"
  54. android:text="+"
  55. android:textColor="@color/red"
  56. android:textSize="48sp" />
  57. </com.tencent.tencentmap.mapsdk.maps.MapView>
  58. <LinearLayout
  59. android:id="@+id/ll_zoom"
  60. android:layout_width="wrap_content"
  61. android:layout_height="wrap_content"
  62. android:layout_marginEnd="20dp"
  63. android:layout_marginBottom="120dp"
  64. android:orientation="vertical"
  65. android:background="@drawable/radius_border_15"
  66. app:layout_constraintBottom_toBottomOf="parent"
  67. app:layout_constraintEnd_toEndOf="parent">
  68. <TextView
  69. android:id="@+id/tv_enlarge"
  70. android:layout_width="50dp"
  71. android:layout_height="50dp"
  72. android:layout_gravity="center_horizontal"
  73. android:layout_marginTop="10dp"
  74. android:layout_marginBottom="5dp"
  75. android:gravity="center"
  76. android:text="+"
  77. android:textColor="@color/black"
  78. android:textSize="32sp"
  79. android:textStyle="bold" />
  80. <TextView
  81. android:id="@+id/tv_narrow"
  82. android:layout_width="50dp"
  83. android:layout_height="50dp"
  84. android:layout_gravity="center_horizontal"
  85. android:layout_marginTop="5dp"
  86. android:layout_marginBottom="10dp"
  87. android:gravity="center"
  88. android:text="-"
  89. android:textColor="@color/black"
  90. android:textSize="32sp"
  91. android:textStyle="bold" />
  92. </LinearLayout>
  93. <LinearLayout
  94. android:id="@+id/ll_goMyPlace"
  95. android:layout_width="wrap_content"
  96. android:layout_height="wrap_content"
  97. android:layout_marginStart="20dp"
  98. android:layout_marginBottom="55dp"
  99. android:orientation="horizontal"
  100. android:background="@drawable/radius_border_15"
  101. app:layout_constraintBottom_toBottomOf="parent"
  102. app:layout_constraintStart_toStartOf="parent">
  103. <ImageButton
  104. android:id="@+id/img_btn_goMyPlace"
  105. android:layout_width="54dp"
  106. android:layout_height="54dp"
  107. android:backgroundTint="@color/white"
  108. android:src="@drawable/ic_go_my_place"
  109. tools:ignore="ContentDescription" />
  110. </LinearLayout>
  111. <!-- ll_pop布局中包含的是出现、搜索、图层按钮对应的功能 -->
  112. <!-- 显示互斥布局rg_travel;ll_search1、sv_searchPoi、ll_search2;ll_layer -->
  113. <LinearLayout
  114. android:id="@+id/ll_pop"
  115. android:layout_width="match_parent"
  116. android:layout_height="wrap_content"
  117. android:layout_marginTop="15dp"
  118. android:orientation="vertical"
  119. android:background="@drawable/radius_border_15"
  120. app:layout_constraintEnd_toEndOf="@id/mapView"
  121. app:layout_constraintStart_toStartOf="@id/mapView"
  122. app:layout_constraintTop_toTopOf="@id/mapView">
  123. <RadioGroup
  124. android:id="@+id/rg_travel"
  125. android:layout_width="match_parent"
  126. android:layout_height="wrap_content"
  127. android:layout_margin="5dp"
  128. android:orientation="horizontal" >
  129. <RadioButton
  130. android:id="@+id/rb_walk"
  131. android:layout_width="0dp"
  132. android:layout_height="wrap_content"
  133. android:layout_weight="1"
  134. android:checked="true"
  135. android:text="步行"
  136. android:textColor="@color/black"
  137. android:textSize="17sp" />
  138. <RadioButton
  139. android:id="@+id/rb_drive"
  140. android:layout_width="0dp"
  141. android:layout_height="wrap_content"
  142. android:layout_weight="1"
  143. android:checked="false"
  144. android:text="驾车"
  145. android:textColor="@color/black"
  146. android:textSize="17sp" />
  147. <Button
  148. android:id="@+id/btn_start"
  149. android:layout_width="80dp"
  150. android:layout_height="wrap_content"
  151. android:text="出发"
  152. tools:ignore="ButtonStyle" />
  153. <Button
  154. android:id="@+id/btn_redo"
  155. android:layout_width="80dp"
  156. android:layout_marginStart="5dp"
  157. android:layout_marginEnd="5dp"
  158. android:layout_height="wrap_content"
  159. android:text="重来"
  160. tools:ignore="ButtonStyle" />
  161. </RadioGroup>
  162. <LinearLayout
  163. android:id="@+id/ll_search1"
  164. android:layout_width="match_parent"
  165. android:layout_height="wrap_content"
  166. android:layout_margin="5dp"
  167. android:orientation="horizontal">
  168. <TextView
  169. android:id="@+id/tv_searchType"
  170. android:layout_width="wrap_content"
  171. android:layout_height="wrap_content"
  172. android:layout_gravity="center"
  173. android:layout_marginStart="10dp"
  174. android:textColor="@color/black"
  175. android:textSize="16sp"
  176. android:text="搜索方式:" />
  177. <Spinner
  178. android:id="@+id/sp_searchType"
  179. android:layout_width="wrap_content"
  180. android:layout_height="wrap_content"
  181. android:entries="@array/searchType" />
  182. <TextView
  183. android:layout_width="wrap_content"
  184. android:layout_height="match_parent"
  185. android:gravity="center"
  186. android:text="在"
  187. android:textColor="@color/black"
  188. android:textSize="17sp" />
  189. <EditText
  190. android:id="@+id/et_scope"
  191. android:layout_width="0dp"
  192. android:layout_height="match_parent"
  193. android:layout_weight="1"
  194. android:gravity="center"
  195. android:background="@drawable/editext_selector"
  196. android:textColor="@color/black"
  197. android:textSize="17sp"
  198. android:hint=" "
  199. android:autofillHints="范围"
  200. android:inputType="none"/>
  201. <TextView
  202. android:id="@+id/tv_scope_desc"
  203. android:layout_width="wrap_content"
  204. android:layout_height="match_parent"
  205. android:gravity="center"
  206. android:layout_marginEnd="5dp"
  207. android:text="市内找"
  208. android:textColor="@color/black"
  209. android:textSize="17sp" />
  210. </LinearLayout>
  211. <LinearLayout
  212. android:id="@+id/ll_search2"
  213. android:layout_width="match_parent"
  214. android:layout_height="wrap_content"
  215. android:layout_marginStart="10dp"
  216. android:layout_marginEnd="10dp"
  217. android:orientation="horizontal">
  218. <SearchView
  219. android:id="@+id/sv_searchPoi"
  220. android:layout_width="match_parent"
  221. android:layout_height="wrap_content"
  222. android:background="@color/gray_245" />
  223. </LinearLayout>
  224. <LinearLayout
  225. android:id="@+id/ll_search3"
  226. android:layout_width="match_parent"
  227. android:layout_height="wrap_content"
  228. android:gravity="center_horizontal"
  229. android:layout_marginBottom="5dp"
  230. android:orientation="horizontal">
  231. <Button
  232. android:id="@+id/btn_next_data"
  233. android:layout_width="100dp"
  234. android:layout_height="wrap_content"
  235. android:layout_marginEnd="5dp"
  236. android:text="下一组"
  237. tools:ignore="ButtonStyle" />
  238. <Button
  239. android:id="@+id/btn_clearMarked"
  240. android:layout_width="100dp"
  241. android:layout_marginStart="5dp"
  242. android:layout_height="wrap_content"
  243. android:text="清除标记"
  244. tools:ignore="ButtonStyle" />
  245. </LinearLayout>
  246. <LinearLayout
  247. android:id="@+id/ll_layer"
  248. android:layout_width="match_parent"
  249. android:layout_height="wrap_content"
  250. android:orientation="horizontal">
  251. <RadioGroup
  252. android:id="@+id/rg_layer"
  253. android:layout_width="match_parent"
  254. android:layout_height="wrap_content"
  255. android:layout_marginTop="5dp"
  256. android:layout_marginBottom="5dp"
  257. android:orientation="horizontal" >
  258. <RadioButton
  259. android:id="@+id/rb_common"
  260. android:layout_width="0dp"
  261. android:layout_height="wrap_content"
  262. android:layout_weight="1"
  263. android:checked="true"
  264. android:text="普通"
  265. android:textColor="@color/black"
  266. android:textSize="17sp" />
  267. <RadioButton
  268. android:id="@+id/rb_satellite"
  269. android:layout_width="0dp"
  270. android:layout_height="wrap_content"
  271. android:layout_weight="1"
  272. android:checked="false"
  273. android:text="卫星"
  274. android:textColor="@color/black"
  275. android:textSize="17sp" />
  276. <CheckBox
  277. android:id="@+id/ck_traffic"
  278. android:layout_width="wrap_content"
  279. android:layout_height="wrap_content"
  280. android:checked="false"
  281. android:text="交通情况"
  282. android:textColor="@color/black"
  283. android:textSize="17sp" />
  284. <CheckBox
  285. android:id="@+id/ck_centerPoint"
  286. android:layout_width="30dp"
  287. android:layout_height="wrap_content"
  288. android:layout_marginStart="10dp"
  289. android:checked="false"
  290. android:text=""
  291. android:textColor="@color/black"
  292. android:textSize="17sp" />
  293. <Button
  294. android:id="@+id/btn_getCenter"
  295. android:layout_width="78dp"
  296. android:layout_height="wrap_content"
  297. android:layout_marginEnd="5dp"
  298. android:text="中心点"/>
  299. </RadioGroup>
  300. </LinearLayout>
  301. </LinearLayout>
  302. </androidx.constraintlayout.widget.ConstraintLayout>

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/人工智能uu/article/detail/976889
推荐阅读
相关标签
  

闽ICP备14008679号