image.png
build.gradle(Moudle.app)依赖
implementation 'com.amap.api:3dmap:latest.integration'
implementation 'com.amap.api:location:latest.integration'
implementation 'com.amap.api:search:latest.integration'
配置
defaultConfig {
applicationId "包名"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
multiDexEnabled true
ndk {
//选择要添加的对应cpu类型的.so库。
//热修复支持五种
abiFilters 'arm64-v8a', 'armeabi', 'armeabi-v7a'
}
}
androidmanifest配置
<meta-data android:name="com.amap.api.v2.apikey" android:value="高德地图官网申请"></meta-data>
<service android:name="com.amap.api.location.APSService"></service>
布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:background="@color/white"
android:layout_width="match_parent" android:layout_height="match_parent">
<include
layout="@layout/activity_left_title_text_view"/>
<FrameLayout
android:layout_margin="@dimen/dp_10"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_33">
<EditText
android:id="@+id/etSearch"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/hui_20_circle_white_shape_bg"
android:drawableLeft="@mipmap/search_hui"
android:drawablePadding="@dimen/dp_6"
android:hint="小区/写字楼/学校等"
android:paddingLeft="@dimen/dp_77"
android:singleLine="true"
android:imeOptions="actionSearch"
android:textColorHint="@color/hui_ffc"
android:textSize="@dimen/sp_15" />
<TextView
android:id="@+id/tvCity"
android:drawablePadding="@dimen/dp_5"
android:drawableRight="@mipmap/ic_local"
android:layout_marginLeft="@dimen/dp_10"
android:text="城市"
android:singleLine="true"
android:maxEms="3"
android:ellipsize="end"
android:textSize="@dimen/sp_15"
android:textColor="@color/hui_ff6"
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
<ImageView
android:id="@+id/ivClear"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|center"
android:layout_marginRight="@dimen/dp_15"
android:src="@mipmap/ic_clear"
android:visibility="gone" />
</FrameLayout>
<com.amap.api.maps.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_260" />
<LinearLayout
android:paddingTop="@dimen/dp_17"
android:paddingBottom="@dimen/dp_17"
android:paddingLeft="@dimen/dp_10"
android:paddingRight="@dimen/dp_10"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:textColor="@color/hui_ffb"
android:textSize="@dimen/sp_12"
android:text="当前定位"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<RelativeLayout
android:layout_marginTop="@dimen/dp_10"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tvLocal"
android:layout_toLeftOf="@+id/tvChoose"
android:layout_alignParentLeft="true"
android:layout_marginRight="@dimen/dp_15"
android:singleLine="true"
android:ellipsize="end"
android:textColor="@color/hui_ff6"
android:textSize="@dimen/sp_17"
android:text="当前位置"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/tvChoose"
android:layout_alignParentRight="true"
android:textColor="@color/hui_ff8"
android:textSize="@dimen/sp_15"
android:text="使用此地址"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</RelativeLayout>
<TextView
android:layout_marginTop="@dimen/dp_10"
android:id="@+id/tvLocalInfo"
android:layout_toLeftOf="@+id/tvChoose"
android:layout_marginRight="@dimen/dp_80"
android:singleLine="true"
android:ellipsize="end"
android:textColor="@color/hui_ff6"
android:textSize="@dimen/sp_12"
android:text="位置详情"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
<View
android:background="@color/hui_fff6"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_10"/>
<androidx.core.widget.NestedScrollView
android:paddingBottom="@dimen/dp_10"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rvMapList"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</androidx.core.widget.NestedScrollView>
</LinearLayout>
activity实现代码:
import android.graphics.Color
import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.view.KeyEvent
import android.view.View
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import android.widget.TextView
import androidx.recyclerview.widget.LinearLayoutManager
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.CameraUpdateFactory
import com.amap.api.maps.LocationSource
import com.amap.api.maps.model.*
import com.amap.api.maps.model.animation.Animation
import com.amap.api.maps.model.animation.TranslateAnimation
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.poisearch.PoiResult
import com.amap.api.services.poisearch.PoiSearch
import com.dsy.jxih.R
import com.dsy.jxih.adapter.PositionAdapter
import com.dsy.jxih.base.BaseActivity
import com.dsy.jxih.tools.PublicTools
import kotlinx.android.synthetic.main.activity_left_title_text_view.*
import kotlinx.android.synthetic.main.activity_map_choose_addr_view.*
import org.jetbrains.anko.toast
/**
*@Created by wrs on 2020/9/18,16:45
*@packageName: com.dsy.jxih.activity
*@Description: 地图定位选点
*/
class MapChooseAddrActivity : BaseActivity(),View.OnClickListener, LocationSource,
AMapLocationListener, AMap.OnMapLoadedListener, AMap.OnCameraChangeListener,
PoiSearch.OnPoiSearchListener,TextView.OnEditorActionListener {
var aMap: AMap? = null
var mySelfLocationStyle: MyLocationStyle? = null
var mListener: LocationSource.OnLocationChangedListener? = null
var mlocationClient: AMapLocationClient? = null
var mLocationOption: AMapLocationClientOption? = null
var screenMarker: Marker? = null
var latLon: LatLng? = null
var choosePosition = 0
//poi附近搜索// Poi查询条件类
var query: PoiSearch.Query? = null
var poiSearch: PoiSearch? = null
var keyWord = ""
var lat = 0.0
var lon = 0.0
var positionAdtapter: PositionAdapter? = null
var listPosition = ArrayList<PoiItem>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_map_choose_addr_view)
mapView.onCreate(savedInstanceState);// 此方法必须重写
initView()
initMap()
initActLocation()
initPoi()
initData()
initListener()
}
override fun initView() {
tvTitle.text = "所在区域"
}
fun initMap() {
aMap = mapView.getMap()
mySelfLocationStyle =
MyLocationStyle().apply {
interval(2000) //设置连续定位模式下的定位间隔,只在连续定位模式下生效,单次定位模式下不会生效。单位为毫秒。
myLocationType(MyLocationStyle.LOCATION_TYPE_FOLLOW_NO_CENTER);//连续定位、且将视角移动到地图中心点,定位蓝点跟随设备移动。(1秒1次定位)
}
mySelfLocationStyle?.strokeColor(Color.TRANSPARENT)
mySelfLocationStyle?.radiusFillColor(Color.argb(0, 0, 0, 0))
mySelfLocationStyle?.strokeWidth(1.0f)
with(aMap!!) {
isTrafficEnabled = true;// 显示实时交通状况
setMapType(AMap.MAP_TYPE_NORMAL);// 卫星地图模式MAP_TYPE_SATELLITE
myLocationStyle = mySelfLocationStyle //设置定位蓝点的Style
isMyLocationEnabled = true // 设置为true表示启动显示定位蓝点,false表示隐藏定位蓝点并不进行定位,默认是false。
// minZoomLevel = 16f //设置显示比例
moveCamera(CameraUpdateFactory.zoomTo(16f)) //设置显示比例 要与上面的一个设置联合使用才会起效果
setLocationSource(this@MapChooseAddrActivity)// 设置定位监听
setMyLocationEnabled(true) // 设置为true表示显示定位层并可触发定位,false表示隐藏定位层并不可触发定位,默认是false
setMyLocationType(AMap.LOCATION_TYPE_LOCATE)// 设置定位的类型为定位模式,有定位、跟随或地图根据面向方向旋转几种
setOnMapLoadedListener(this@MapChooseAddrActivity)//监听地图是否加载完
setOnCameraChangeListener(this@MapChooseAddrActivity)//设置可视范围变化时的回调的接口方法
}
aMap?.let {
it.getUiSettings().apply {
isMyLocationButtonEnabled = true//设置默认定位按钮是否显示,非必需设置。
isScaleControlsEnabled = true //显示比列尺
isCompassEnabled = false //指蓝针
isZoomControlsEnabled = true //返回缩放按钮是否可见
}
}
}
override fun initData() {
positionAdtapter = PositionAdapter(this,listPosition)
val lm = LinearLayoutManager(this)
lm.orientation = LinearLayoutManager.VERTICAL
with(rvMapList){
layoutManager = lm
adapter = positionAdtapter
}
}
//地图是否加载完监听事件
override fun onMapLoaded() {
addMarkerInScreenCenter()
}
//在地图状态改变完成时回调此方法。
override fun onCameraChangeFinish(position: CameraPosition?) {
//屏幕中心的Marker跳动
startJumpAnimation()
lon = position?.target?.longitude ?: 0.0
lat = position?.target?.latitude ?: 0.0
Log.e("经纬度", "======经度======:" + lon)
Log.e("经纬度", "======维度======:" + lat)
initPoi()
}
override fun onCameraChange(position: CameraPosition?) {
}
/**
* 屏幕中心marker 跳动
*/
fun startJumpAnimation() {
if (screenMarker != null && aMap != null) { //根据屏幕距离计算需要移动的目标点
val latLng = screenMarker?.position
val point = aMap!!.projection.toScreenLocation(latLng)
point.y -= PublicTools.tools.dip2px(this, 125f)
val target = aMap?.projection?.fromScreenLocation(point)
//使用TranslateAnimation,填写一个需要移动的目标点
val animation: Animation = TranslateAnimation(target)
animation.setInterpolator { input ->
// 模拟重加速度的interpolator
if (input <= 0.5) {
(0.5f - 2 * (0.5 - input) * (0.5 - input)).toFloat()
} else {
(0.5f - Math.sqrt((input - 0.5f) * (1.5f - input).toDouble())).toFloat()
}
}
//整个移动所需要的时间
animation.setDuration(600)
//设置动画
screenMarker?.setAnimation(animation)
//开始动画
screenMarker?.startAnimation()
} else {
Log.e("amap", "screenMarker is null")
}
}
/**
* 在屏幕中心添加一个Marker
*/
private fun addMarkerInScreenCenter() {
val latLng = aMap!!.cameraPosition.target
val screenPosition = aMap!!.projection.toScreenLocation(latLng)
screenMarker = aMap!!.addMarker(
MarkerOptions()
.anchor(0.5f, 0.5f)
.icon(BitmapDescriptorFactory.fromResource(R.mipmap.purple_pin))
)
//设置Marker在屏幕上,不跟随地图移动
screenMarker?.setPositionByPixels(screenPosition.x, screenPosition.y)
}
fun initActLocation() {
if (mlocationClient == null) { //初始化定位
//初始化定位参数
mLocationOption = AMapLocationClientOption().apply {
locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy//设置为高精度定位模式
}
mlocationClient = AMapLocationClient(this)
//设置定位回调监听
mlocationClient?.setLocationListener(this)
//设置定位参数
mlocationClient?.setLocationOption(mLocationOption)
mlocationClient?.startLocation() //启动定位
}
}
override fun deactivate() {
if (mlocationClient != null) {
mlocationClient?.stopLocation();
mlocationClient?.onDestroy();
}
mlocationClient = null;
}
override fun activate(listener: LocationSource.OnLocationChangedListener?) {
mListener = listener;
if (mlocationClient != null) {
mlocationClient?.stopLocation();
mlocationClient?.onDestroy();
}
mlocationClient = null;
}
override fun onLocationChanged(amapLocation: AMapLocation?) {
if (mListener != null && amapLocation != null) {
if (amapLocation != null
&& amapLocation.errorCode === 0
) {
mListener?.onLocationChanged(amapLocation) // 显示系统小蓝点
mlocationClient?.stopLocation()
tvCity.text = amapLocation.city
tvLocal.text = amapLocation.aoiName
tvLocalInfo.text = amapLocation.address
// province city district
lon = amapLocation.longitude
lat = amapLocation.latitude
choosePosition = 0
latLon = LatLng(lat, lon)
initPoi()
} else {
val errText =
"定位失败," + amapLocation.errorCode.toString() + ": " + amapLocation.errorInfo
Log.e("AmapErr", errText)
}
}
}
/**
* 初始化搜索
*/
fun initPoi() {
// 第一个参数表示搜索字符串,第二个参数表示poi搜索类型,第三个参数表示poi搜索区域(空字符串代表全国)
query = PoiSearch.Query(keyWord, null, null)
query?.pageSize = 30 // 设置每页最多返回多少条poiitem
query?.pageNum = 0 // 设置查第一页
query?.extensions=PoiSearch.EXTENSIONS_ALL //每次搜索都返回省市县信息
poiSearch = PoiSearch(this, query)
poiSearch?.setOnPoiSearchListener(this)
if (TextUtils.isEmpty(keyWord)){//搜索内容为空是,按照经纬度来查询附近地名
poiSearch?.setBound(PoiSearch.SearchBound(LatLonPoint(lat, lon), 0,true)) //根据设置的经纬度来查
}else{//模糊搜索时使用一下配置
poiSearch?.bound = null
}
// 设置搜索区域为以lp点为圆心,其周围5000米范围
poiSearch?.searchPOIAsyn() // 异步搜索
}
override fun onPoiItemSearched(p0: PoiItem?, rcode: Int) {
}
override fun onPoiSearched(result: PoiResult?, rcode: Int) {
if (rcode == AMapException.CODE_AMAP_SUCCESS) {
if (result?.query == query) {// 是否是同一条
var poiItems = result?.pois
if (null != poiItems && poiItems!!.size > 0) {
Log.e("结果", "搜索到附近地名了")
listPosition.clear()
// positionAdtapter?.setChoosePosition(choosePosition)
listPosition.addAll(poiItems)
positionAdtapter?.notifyDataSetChanged()
} else {
toast("请稍后")
}
}
} else {
toast("" + rcode)
}
}
override fun onDestroy() {
super.onDestroy()
mapView.onDestroy()
if (null != mlocationClient) {
mlocationClient?.onDestroy()
}
listPosition?.let {
it.clear()
null
}
}
/**
* 方法必须重写
*/
override fun onResume() {
super.onResume()
mapView?.onResume()
}
/**
* 方法必须重写
*/
override fun onPause() {
super.onPause()
mapView?.onPause()
}
override fun initListener() {
tvChoose.setOnClickListener(this)
ivBack.setOnClickListener(this)
etSearch.setOnEditorActionListener(this)
}
override fun onClick(v: View?) {
when(v?.id){
R.id.ivBack ->{//返回
finish()
}
R.id.tvChoose ->{//选择当前定位
toast("选择当前定位")
}
}
}
override fun onEditorAction(v: TextView?, actionId: Int, event: KeyEvent?): Boolean {
if (actionId == EditorInfo.IME_ACTION_SEARCH){
val searchStr = etSearch.editableText.toString().trim()
if (TextUtils.isEmpty(searchStr)){
keyWord = ""
}else{
val imm = getSystemService(INPUT_METHOD_SERVICE) as? InputMethodManager
imm?.hideSoftInputFromWindow(v?.getWindowToken(), 0)
keyWord = searchStr
initPoi()
}
return false
}
return true
}
}
adapter适配器
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.amap.api.services.core.PoiItem
import com.dsy.jxih.R
import com.dsy.jxih.iml.onAdapterAnyListener
class PositionAdapter(var context: Context,var listData:ArrayList<PoiItem>) : RecyclerView.Adapter<PositionAdapter.ViewHolder>() {
private var listener: onAdapterAnyListener? = null
fun setAdapterClickListener(listener: onAdapterAnyListener) {
this.listener = listener
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(context).inflate(R.layout.adapter_map_choose_item_view,parent,false)
return ViewHolder(view)
}
override fun getItemCount(): Int {
return listData.size
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
with(holder){
val bean = listData.get(position)
tvAddr?.text = bean.title
tvAddrInfo?.text = bean.snippet
}
}
class ViewHolder(view: View) :RecyclerView.ViewHolder(view){
var tvAddr:TextView? = null
var tvAddrInfo:TextView? = null
init {
tvAddr = view.findViewById(R.id.tvAddr)
tvAddrInfo = view.findViewById(R.id.tvAddrInfo)
}
}
}
adapter适配器的布局
<?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"
android:id="@+id/llLay"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_15"
android:orientation="vertical"
android:paddingLeft="@dimen/dp_10"
android:paddingRight="@dimen/dp_10">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/tvAddr"
android:layout_alignParentLeft="true"
android:layout_marginRight="@dimen/dp_15"
android:layout_toLeftOf="@+id/ivLocal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
android:text="北海国际仲裁院"
android:textColor="@color/hui_ff"
android:textSize="@dimen/sp_17" />
<ImageView
android:id="@+id/ivLocal"
android:layout_width="@dimen/dp_20"
android:layout_height="@dimen/dp_20"
android:layout_alignParentRight="true"
android:adjustViewBounds="true"
android:src="@mipmap/ic_map" />
</RelativeLayout>
<TextView
android:id="@+id/tvAddrInfo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_10"
android:layout_marginRight="@dimen/dp_80"
android:layout_toLeftOf="@+id/tvChoose"
android:ellipsize="end"
android:singleLine="true"
android:text="深圳市宝安区宝安中心前海湾卓越时代广场…"
android:textColor="@color/hui_ff6"
android:textSize="@dimen/sp_12" />
</LinearLayout>
有需要的码农可以直接拿去使用
网友评论