美文网首页Android 开发必备
android 使用高德地图定位、显示地图、PIO搜索

android 使用高德地图定位、显示地图、PIO搜索

作者: hao_developer | 来源:发表于2020-09-18 20:14 被阅读0次
image.png
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>

有需要的码农可以直接拿去使用

相关文章

网友评论

    本文标题:android 使用高德地图定位、显示地图、PIO搜索

    本文链接:https://www.haomeiwen.com/subject/yrxsyktx.html