android 使用高德地圖定位、顯示地圖、PIO搜索

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 {
            //選擇要添加的對(duì)應(yīng)cpu類型的.so庫(kù)。
            //熱修復(fù)支持五種
            abiFilters 'arm64-v8a', 'armeabi', 'armeabi-v7a'
        }
    }

androidmanifest配置

 <meta-data android:name="com.amap.api.v2.apikey" android:value="高德地圖官網(wǎng)申請(qǐng)"></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="小區(qū)/寫(xiě)字樓/學(xué)校等"
            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="當(dāng)前定位"
            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="當(dāng)前位置"
                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實(shí)現(xiàn)代碼:

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: 地圖定位選點(diǎn)
 */
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);// 此方法必須重寫(xiě)
        initView()
        initMap()
        initActLocation()
        initPoi()
        initData()
        initListener()
    }

    override fun initView() {
        tvTitle.text = "所在區(qū)域"
    }

    fun initMap() {
        aMap = mapView.getMap()
        mySelfLocationStyle =
            MyLocationStyle().apply {
                interval(2000) //設(shè)置連續(xù)定位模式下的定位間隔,只在連續(xù)定位模式下生效,單次定位模式下不會(huì)生效。單位為毫秒。
                myLocationType(MyLocationStyle.LOCATION_TYPE_FOLLOW_NO_CENTER);//連續(xù)定位、且將視角移動(dòng)到地圖中心點(diǎn),定位藍(lán)點(diǎn)跟隨設(shè)備移動(dòng)。(1秒1次定位)
            }
        mySelfLocationStyle?.strokeColor(Color.TRANSPARENT)
        mySelfLocationStyle?.radiusFillColor(Color.argb(0, 0, 0, 0))
        mySelfLocationStyle?.strokeWidth(1.0f)

        with(aMap!!) {
            isTrafficEnabled = true;// 顯示實(shí)時(shí)交通狀況
            setMapType(AMap.MAP_TYPE_NORMAL);// 衛(wèi)星地圖模式MAP_TYPE_SATELLITE
            myLocationStyle = mySelfLocationStyle //設(shè)置定位藍(lán)點(diǎn)的Style
            isMyLocationEnabled = true // 設(shè)置為true表示啟動(dòng)顯示定位藍(lán)點(diǎn),false表示隱藏定位藍(lán)點(diǎn)并不進(jìn)行定位,默認(rèn)是false。
//            minZoomLevel = 16f //設(shè)置顯示比例
            moveCamera(CameraUpdateFactory.zoomTo(16f)) //設(shè)置顯示比例 要與上面的一個(gè)設(shè)置聯(lián)合使用才會(huì)起效果
            setLocationSource(this@MapChooseAddrActivity)// 設(shè)置定位監(jiān)聽(tīng)
            setMyLocationEnabled(true) // 設(shè)置為true表示顯示定位層并可觸發(fā)定位,false表示隱藏定位層并不可觸發(fā)定位,默認(rèn)是false
            setMyLocationType(AMap.LOCATION_TYPE_LOCATE)// 設(shè)置定位的類型為定位模式,有定位、跟隨或地圖根據(jù)面向方向旋轉(zhuǎn)幾種
            setOnMapLoadedListener(this@MapChooseAddrActivity)//監(jiān)聽(tīng)地圖是否加載完
            setOnCameraChangeListener(this@MapChooseAddrActivity)//設(shè)置可視范圍變化時(shí)的回調(diào)的接口方法
        }

        aMap?.let {
            it.getUiSettings().apply {
                isMyLocationButtonEnabled = true//設(shè)置默認(rèn)定位按鈕是否顯示,非必需設(shè)置。
                isScaleControlsEnabled = true //顯示比列尺
                isCompassEnabled = false //指藍(lán)針
                isZoomControlsEnabled = true //返回縮放按鈕是否可見(jiàn)
            }
        }
    }

    override fun initData() {
        positionAdtapter = PositionAdapter(this,listPosition)
        val lm = LinearLayoutManager(this)
        lm.orientation = LinearLayoutManager.VERTICAL
        with(rvMapList){
            layoutManager = lm
            adapter = positionAdtapter
        }
    }

    //地圖是否加載完監(jiān)聽(tīng)事件
    override fun onMapLoaded() {
        addMarkerInScreenCenter()
    }

    //在地圖狀態(tài)改變完成時(shí)回調(diào)此方法。
    override fun onCameraChangeFinish(position: CameraPosition?) {
        //屏幕中心的Marker跳動(dòng)
        startJumpAnimation()

        lon = position?.target?.longitude ?: 0.0
        lat = position?.target?.latitude ?: 0.0
        Log.e("經(jīng)緯度", "======經(jīng)度======:" + lon)
        Log.e("經(jīng)緯度", "======維度======:" + lat)
        initPoi()
    }

    override fun onCameraChange(position: CameraPosition?) {
    }

    /**
     * 屏幕中心marker 跳動(dòng)
     */
    fun startJumpAnimation() {
        if (screenMarker != null && aMap != null) { //根據(jù)屏幕距離計(jì)算需要移動(dòng)的目標(biāo)點(diǎn)
            val latLng = screenMarker?.position
            val point = aMap!!.projection.toScreenLocation(latLng)
            point.y -= PublicTools.tools.dip2px(this, 125f)
            val target = aMap?.projection?.fromScreenLocation(point)
            //使用TranslateAnimation,填寫(xiě)一個(gè)需要移動(dòng)的目標(biāo)點(diǎn)
            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()
                }
            }
            //整個(gè)移動(dòng)所需要的時(shí)間
            animation.setDuration(600)
            //設(shè)置動(dòng)畫(huà)
            screenMarker?.setAnimation(animation)
            //開(kāi)始動(dòng)畫(huà)
            screenMarker?.startAnimation()
        } else {
            Log.e("amap", "screenMarker is null")
        }
    }

    /**
     * 在屏幕中心添加一個(gè)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))
        )
        //設(shè)置Marker在屏幕上,不跟隨地圖移動(dòng)
        screenMarker?.setPositionByPixels(screenPosition.x, screenPosition.y)
    }

    fun initActLocation() {
        if (mlocationClient == null) { //初始化定位
            //初始化定位參數(shù)
            mLocationOption = AMapLocationClientOption().apply {
                locationMode = AMapLocationClientOption.AMapLocationMode.Hight_Accuracy//設(shè)置為高精度定位模式
            }
            mlocationClient = AMapLocationClient(this)
            //設(shè)置定位回調(diào)監(jiān)聽(tīng)
            mlocationClient?.setLocationListener(this)
            //設(shè)置定位參數(shù)
            mlocationClient?.setLocationOption(mLocationOption)
            mlocationClient?.startLocation() //啟動(dòng)定位
        }
    }

    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) // 顯示系統(tǒng)小藍(lán)點(diǎn)
                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() {
        // 第一個(gè)參數(shù)表示搜索字符串,第二個(gè)參數(shù)表示poi搜索類型,第三個(gè)參數(shù)表示poi搜索區(qū)域(空字符串代表全國(guó))
        query = PoiSearch.Query(keyWord, null, null)
        query?.pageSize = 30 // 設(shè)置每頁(yè)最多返回多少條poiitem
        query?.pageNum = 0 // 設(shè)置查第一頁(yè)
       query?.extensions=PoiSearch.EXTENSIONS_ALL //每次搜索都返回省市縣信息

        poiSearch = PoiSearch(this, query)
        poiSearch?.setOnPoiSearchListener(this)
        if (TextUtils.isEmpty(keyWord)){//搜索內(nèi)容為空是,按照經(jīng)緯度來(lái)查詢附近地名
            poiSearch?.setBound(PoiSearch.SearchBound(LatLonPoint(lat, lon), 0,true)) //根據(jù)設(shè)置的經(jīng)緯度來(lái)查
        }else{//模糊搜索時(shí)使用一下配置
            poiSearch?.bound = null
        }
        // 設(shè)置搜索區(qū)域?yàn)橐詌p點(diǎn)為圓心,其周圍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("結(jié)果", "搜索到附近地名了")
                    listPosition.clear()
//                    positionAdtapter?.setChoosePosition(choosePosition)
                    listPosition.addAll(poiItems)
                    positionAdtapter?.notifyDataSetChanged()
                } else {
                    toast("請(qǐng)稍后")
                }

            }
        } else {
            toast("" + rcode)
        }
    }


    override fun onDestroy() {
        super.onDestroy()
        mapView.onDestroy()
        if (null != mlocationClient) {
            mlocationClient?.onDestroy()
        }
        listPosition?.let {
            it.clear()
            null
        }
    }

    /**
     * 方法必須重寫(xiě)
     */
    override fun onResume() {
        super.onResume()
        mapView?.onResume()
    }

    /**
     * 方法必須重寫(xiě)
     */
    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 ->{//選擇當(dāng)前定位
                toast("選擇當(dāng)前定位")
            }
        }
    }

    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="北海國(guó)際仲裁院"
            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="深圳市寶安區(qū)寶安中心前海灣卓越時(shí)代廣場(chǎng)…"
        android:textColor="@color/hui_ff6"
        android:textSize="@dimen/sp_12" />


</LinearLayout>

有需要的碼農(nóng)可以直接拿去使用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容