高得地圖 +數據綁定(databinding) + BaseQuickAdapter 自定義地圖選點!

自定義地圖選擇器

    根據傳入的經緯度定位到指定位置,如果爲空就定位到當前所在位置
    根據用戶輸入的字符串顯示poi聯想數據列表,點擊item把對應的位置顯示在地圖上
    點擊確認按鈕根據eventbus將數據回傳

	好了。話不多說,直接開衝!!!

MapActivity

package cn.sunsapp.owner.controller.activity;

import android.graphics.Color;
import android.location.Location;
import android.os.Bundle;
import android.os.PersistableBundle;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.databinding.DataBindingUtil;
import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import com.amap.api.location.AMapLocation;
import com.amap.api.maps.AMap;
import com.amap.api.maps.AMapOptions;
import com.amap.api.maps.CameraUpdate;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.MapView;
import com.amap.api.maps.model.CameraPosition;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.MyLocationStyle;
import com.amap.api.services.core.PoiItem;
import com.amap.api.services.help.Inputtips;
import com.amap.api.services.help.InputtipsQuery;
import com.amap.api.services.help.Tip;
import com.amap.api.services.poisearch.PoiResult;
import com.amap.api.services.poisearch.PoiSearch;
import com.basic.lattercore.activities.DBBaseActivity;
import com.basic.lattercore.util.SunsToastUtils;
import com.basic.lattercore.util.click.AntiShakeUtils;
import com.basic.lattercore.util.event.EventBusUtils;
import com.basic.lattercore.util.event.EventMessage;
import com.blankj.utilcode.util.LogUtils;
import com.heytap.mcssdk.utils.LogUtil;
import com.tencent.mm.opensdk.utils.Log;

import org.greenrobot.eventbus.Subscribe;
import org.greenrobot.eventbus.ThreadMode;

import java.util.ArrayList;
import java.util.List;
import java.util.WeakHashMap;

import cn.sunsapp.owner.EventCode;
import cn.sunsapp.owner.R;
import cn.sunsapp.owner.adapter.PoiListAdapter;
import cn.sunsapp.owner.adapter.SearchPlaceListAdapter;
import cn.sunsapp.owner.databinding.ActivityMapBinding;
import cn.sunsapp.owner.util.AMapLocationListener;
import cn.sunsapp.owner.util.AppUtil;
import cn.sunsapp.owner.viewmodel.DBMapActivityViewModel;


public class MapActivity extends DBBaseActivity implements PoiSearch.OnPoiSearchListener {


    EditText etSearchCityPoi;//輸入框
    TextView tvEnsureCommitBtn;//確認按鈕
    MapView mvBranchAddressChoose;
    RecyclerView rvBranchAddressChoose;
    RecyclerView rvSearchByInputText;
    MapView mapView;
    private AMap aMap = null;

    // 定位adapter
    private PoiListAdapter poiListAdapter;
    private SearchPlaceListAdapter searchAdapter;


    private ActivityMapBinding mBinding;
    private DBMapActivityViewModel mViewModel;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ViewModelProvider viewModelProvider = new ViewModelProvider(this);
        mViewModel = viewModelProvider.get(DBMapActivityViewModel.class);
        mBinding = DataBindingUtil.setContentView(this, R.layout.activity_map);
        mBinding.setLifecycleOwner(this);
        mBinding.setModel(mViewModel);
        onBindView(savedInstanceState);
    }


    protected void onBindView(Bundle savedInstanceState) {
        initView();
        initMap(savedInstanceState);
        searchRange();
    }


    /**
     * 實例化mapview,顯示地圖
     *
     * @param savedInstanceState
     */
    private void initMap(Bundle savedInstanceState) {
        mapView = mBinding.mvBranchAddressChoose;
        mapView.onCreate(savedInstanceState);

        if (aMap == null) {
            aMap = mapView.getMap();
        }
        MyLocationStyle myLocationStyle;
        myLocationStyle = new MyLocationStyle();//初始化定位藍點樣式類myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE);//連續定位、且將視角移動到地圖中心點,定位點依照設備方向旋轉,並且會跟隨設備移動。(1秒1次定位)如果不設置myLocationType,默認也會執行此種模式。
        myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATE);
        myLocationStyle.showMyLocation(false);
        myLocationStyle.strokeColor(Color.argb(0, 0, 0, 0));
        myLocationStyle.radiusFillColor(Color.argb(0, 0, 0, 0));
        mapView.getMap().setMyLocationEnabled(true);
        mapView.getMap().setMyLocationStyle(myLocationStyle);
        mapView.getMap().getUiSettings().setMyLocationButtonEnabled(true);
        mapView.getMap().getUiSettings().setZoomControlsEnabled(false);
        mapView.getMap().getUiSettings().setScaleControlsEnabled(true);//顯示比例尺
        mapView.getMap().getUiSettings().setLogoPosition(AMapOptions.LOGO_POSITION_BOTTOM_RIGHT);//設置地圖logo的顯示位置爲右下角(隱藏不了)
//        mapView.getMap().moveCamera(CameraUpdateFactory.zoomTo(18f));


        mapView.getMap().setOnMyLocationChangeListener(new AMap.OnMyLocationChangeListener() {
            @Override
            public void onMyLocationChange(Location location) {
                if (location == null) {
                    return;
                }
                Marker marker;
                MarkerOptions markerOptions;
                markerOptions = new MarkerOptions();
                marker = mapView.getMap().addMarker(markerOptions);
                int width = mapView.getRight() / 2;
                int height = mapView.getBottom() / 2;
                marker.setPositionByPixels(width, height);
                LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());

//                LogUtils.e(mViewModel.getProvLat(),mViewModel.getProvLng(),mViewModel.isFirstLoadList());

                if (!TextUtils.isEmpty(mViewModel.getProvLat()) && mViewModel.isFirstLoadList()) {
                    latLng = new LatLng(Double.valueOf(mViewModel.getProvLat()), Double.valueOf(mViewModel.getProvLng()));
                }
                moveCameraUpdate(mapView, latLng, 18f);

            }
        });


        mapView.getMap().setOnCameraChangeListener(new AMap.OnCameraChangeListener() {
            @Override
            public void onCameraChange(CameraPosition cameraPosition) {

            }

            @Override
            public void onCameraChangeFinish(CameraPosition cameraPosition) {
                if (cameraPosition == null) {
                    return;
                }
                if (mViewModel.isHandDrag() || mViewModel.isFirstLoadList()) {
                    LatLng target = cameraPosition.target;
                    AppUtil.getCircumInfo(mContext, target.latitude, target.longitude);
                    mViewModel.setFirstLoadList(false);
                }
                mViewModel.setHandDrag(true);

            }
        });
    }

    /**
     * 點擊獲取到的聯想數據poi item時,地圖中心點藍點移動到對應的位置
     *
     * @param mv
     * @param ll
     * @param zoom
     */
    private void moveCameraUpdate(MapView mv, LatLng ll, Float zoom) {
        CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(ll, zoom);
        mv.getMap().animateCamera(cameraUpdate);
    }

    /**
     * mapview下面的recycleview實例化和數據的顯示和對應的item點擊事件
     */
    private void initView() {

        initToolbarNav(mBinding.toolbarContainer.toolbar);
        mBinding.toolbarContainer.toolbarTitle.setText("地址選擇");
        mViewModel.setEventCode(getIntent().getIntExtra("event_code", EventCode.CHOOSE_CITY_POI_SUCESS));
        mViewModel.setProvLat(getIntent().getStringExtra("lat"));
        mViewModel.setProvLng(getIntent().getStringExtra("lng"));

        etSearchCityPoi = mBinding.etSearchCityPoi;
        tvEnsureCommitBtn = mBinding.tvEnsureCommitBtn;
        tvEnsureCommitBtn.setOnClickListener(v -> {
            selectCity();
        });
        mvBranchAddressChoose = mBinding.mvBranchAddressChoose;
        rvBranchAddressChoose = mBinding.rvBranchAddressChoose;
        rvSearchByInputText = mBinding.rvSearchByInputText;


        rvBranchAddressChoose.setLayoutManager(new LinearLayoutManager(mContext));
        poiListAdapter = new PoiListAdapter(R.layout.item_branch_poi_list);
        rvBranchAddressChoose.setAdapter(poiListAdapter);
        poiListAdapter.setOnItemClickListener((adapter, view, position) -> {
            poiListAdapter.changeCheckedPositon(position);
            double latlonPointLat = poiListAdapter.getItem(position).getLatLonPoint().getLatitude();
            double latlngPointLng = poiListAdapter.getItem(position).getLatLonPoint().getLongitude();
            LatLng latLngPoint = new LatLng(latlonPointLat, latlngPointLng);
            mViewModel.setHandDrag(false);
            moveCameraUpdate(mapView, latLngPoint, 18f);

        });


        rvSearchByInputText.setLayoutManager(new LinearLayoutManager(mContext));
        searchAdapter = new SearchPlaceListAdapter(R.layout.item_branch_poi_list);
        rvSearchByInputText.setAdapter(searchAdapter);
        searchAdapter.setOnItemClickListener((adapter, view, position) -> {
            double selectLat = searchAdapter.getItem(position).getLatLonPoint().getLatitude();
            double selectLng = searchAdapter.getItem(position).getLatLonPoint().getLongitude();

            ArrayList<PoiItem> data = new ArrayList<>();
            data.add(searchAdapter.getItem(position));
            poiListAdapter.setNewData(data);
            poiListAdapter.changeCheckedPositon(0);
            LatLng selectPoint = new LatLng(selectLat, selectLng);
            moveCameraUpdate(mapView, selectPoint, 18f);
            mViewModel.setSearchClick(true);
            mViewModel.getShowSearchList().setValue(false);
        });

    }

    /**
     * 搜索功能:在edittext中字符串發生變化的時候,自動提示相對應的poi信息,並顯示在對應的recycleview上
     */
    private void searchRange() {


        mViewModel.getSearchWords().observe(this, s -> {
            mViewModel.getShowSearchList().setValue(true);
            if (s.trim().length() == 0) {
                mViewModel.getShowSearchList().setValue(false);
            }
            PoiSearch.Query query = new PoiSearch.Query(s, "", "");
            //keyWord表示搜索字符串,
            //第二個參數表示POI搜索類型,二者選填其一,選用POI搜索類型時建議填寫類型代碼,碼錶可以參考下方(而非文字)
            //cityCode表示POI搜索區域,可以是城市編碼也可以是城市名稱,也可以傳空字符串,空字符串代表全國在全國範圍內進行搜索
            query.setPageSize(50);// 設置每頁最多返回多少條poiitem
            query.setPageNum(1);//設置查詢頁碼
            PoiSearch poiSearch = new PoiSearch(this, query);
            poiSearch.setOnPoiSearchListener(this);
            poiSearch.searchPOIAsyn();

        });

    }

    /**
     * 點擊左上角的位置時彈出省市選擇器,點擊確定按鈕提交選擇的信息
     */
    public void selectCity() {

        PoiItem item = poiListAdapter.getItem(poiListAdapter.getCheckedPosition());

        if (item != null) {
            mViewModel.getEventMap().put("prov", item.getProvinceName());
            mViewModel.getEventMap().put("city", item.getCityName());
            mViewModel.getEventMap().put("county", item.getAdName());
            // 如果沒有詳細地址,就把標題拿出來
            if ("".equals(item.getSnippet())) {
                mViewModel.getEventMap().put("detail", item.getTitle());
            } else {
                mViewModel.getEventMap().put("detail", item.getSnippet());
            }

            mViewModel.getEventMap().put("lat", item.getLatLonPoint().getLatitude());
            mViewModel.getEventMap().put("lng", item.getLatLonPoint().getLongitude());

            EventBusUtils.post(new EventMessage(mViewModel.getEventCode(), mViewModel.getEventMap()));
        }
        finish();

    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        mapView.onDestroy();
    }

    @Override
    protected void onResume() {
        super.onResume();
        mapView.onResume();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mapView.onPause();
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {
        super.onSaveInstanceState(outState, outPersistentState);
        mapView.onSaveInstanceState(outState);
    }

    @Override
    protected boolean isRegisteredEventBus() {
        return true;
    }

    /**
     * 根據傳入的經緯度,獲取相對應的poi聯想數據
     *
     * @param message
     */
    @Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
    public void onGetMessage(EventMessage message) {
        switch (message.getCode()) {
            case EventCode.BRANCH_ADDRESS_LOCATION_POI:
                List<PoiItem> poiData = (List) message.getData();
                rvBranchAddressChoose.scrollToPosition(0);
                poiListAdapter.changeCheckedPositon(0);

                if (mViewModel.isSearchClick()) {
                    poiListAdapter.addData(poiData);
                } else {
                    poiListAdapter.setNewData(poiData);
                }
                mViewModel.setSearchClick(false);
                EventBusUtils.removeSticky(message);
                break;
        }

    }

    @Override
    public void onPoiSearched(PoiResult poiResult, int i) {
        ArrayList<PoiItem> pois = poiResult.getPois();
        searchAdapter.setNewData(pois);
    }

    @Override
    public void onPoiItemSearched(PoiItem poiItem, int i) {

    }
}

activity_map.xml

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <data>

        <import type="cn.sunsapp.owner.viewmodel.DBMapActivityViewModel"/>
        <import type="android.view.View"/>
        <variable
            name="model"
            type="DBMapActivityViewModel" />
    </data>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <include android:id="@+id/toolbarContainer"  layout="@layout/toolbar" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="48dp"
            android:background="@color/white"
            android:orientation="horizontal">

            <EditText
                android:id="@+id/et_search_city_poi"
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_marginLeft="15dp"
                android:layout_marginTop="8dp"
                android:layout_marginRight="15dp"
                android:layout_marginBottom="8dp"
                android:layout_weight="1"
                android:background="#FFF6F6F6"
                android:drawableLeft="@drawable/search"
                android:drawablePadding="11dp"
                android:ellipsize="end"
                android:hint="請輸入網點地址"
                android:paddingLeft="10dp"
                android:singleLine="true"
                android:textColor="@color/normal_text"
                android:textColorHint="#FFC2C2C2"
                android:textSize="14sp"
                android:text="@={model.searchWords}"
                />

            <TextView
                android:id="@+id/tv_ensure_commit_btn"
                style="@style/style_tv_no_font_padding"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_marginTop="8dp"
                android:layout_marginRight="15dp"
                android:layout_marginBottom="8dp"
                android:background="@drawable/shaper_radius5_red_bg"
                android:gravity="center"
                android:paddingLeft="8dp"
                android:paddingRight="8dp"
                android:text="確認"
                android:textColor="@color/white"
                android:textSize="14sp" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/ll_map_and_poi_list"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"
            android:visibility="@{model.showSearchList == true?View.GONE:View.VISIBLE}">

            <com.amap.api.maps.MapView
                android:id="@+id/mv_branch_address_choose"
                android:layout_width="match_parent"
                android:layout_height="250dp" />

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/rv_branch_address_choose"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="@color/white" />
        </LinearLayout>

        <LinearLayout
            android:id="@+id/ll_search_place"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:visibility="@{model.showSearchList == true?View.VISIBLE:View.GONE}"
            >

            <androidx.recyclerview.widget.RecyclerView
                android:id="@+id/rv_search_by_input_text"
                android:layout_width="match_parent"
                android:layout_height="match_parent" />
        </LinearLayout>

    </LinearLayout>
</layout>

PoiListAdapter

package cn.sunsapp.owner.adapter;

import androidx.annotation.NonNull;

import com.amap.api.services.core.PoiItem;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;


import cn.sunsapp.owner.R;

import static com.blankj.utilcode.util.ColorUtils.getColor;

public class PoiListAdapter extends BaseQuickAdapter<PoiItem, BaseViewHolder> {
    public PoiListAdapter(int resLayoutId) {
        super(resLayoutId);
    }

    private int checkedPosition = 0;

    public int getCheckedPosition() {
        return checkedPosition;
    }

    @Override
    protected void convert(@NonNull BaseViewHolder helper, PoiItem item) {
        helper.setText(R.id.tv_poi_address_name, item.getTitle());
        helper.setText(R.id.tv_address_poi_detail_info, item.getSnippet());

        //這裏因爲RecyclerView會導致數據錯亂的原因,要加else判斷
        if (checkedPosition == helper.getLayoutPosition()) {
            helper.setBackgroundRes(R.id.textView21, R.drawable.btn_shape);
            helper.setTextColor(R.id.tv_poi_address_name, getColor(R.color.red));
        } else {
            helper.setBackgroundRes(R.id.textView21, R.drawable.selector_poi_item_ischoose);
            helper.setTextColor(R.id.tv_poi_address_name, getColor(R.color.black));
        }

    }

    /**
     * 改變當前選中項的顏色
     *
     * @param position
     */
    public void changeCheckedPositon(Integer position) {
        this.checkedPosition = position;
        this.notifyDataSetChanged();
    }
}

SearchPlaceListAdapter

package cn.sunsapp.owner.adapter;

import androidx.annotation.NonNull;

import com.amap.api.services.core.PoiItem;
import com.amap.api.services.help.Tip;
import com.chad.library.adapter.base.BaseQuickAdapter;
import com.chad.library.adapter.base.BaseViewHolder;

import cn.sunsapp.owner.R;

public class SearchPlaceListAdapter extends BaseQuickAdapter<PoiItem, BaseViewHolder> {
    public SearchPlaceListAdapter(int resLayoutId) {
        super(resLayoutId);
    }

    @Override
    protected void convert(@NonNull BaseViewHolder helper, PoiItem item) {
        helper.setText(R.id.tv_poi_address_name, item.getTitle());
        helper.setText(R.id.tv_address_poi_detail_info, item.getSnippet());
    }
}

DBMapActivityViewModel

package cn.sunsapp.owner.viewmodel;

import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

import com.blankj.utilcode.util.LogUtils;

import java.util.WeakHashMap;

public class DBMapActivityViewModel extends ViewModel {

    private MutableLiveData<String> searchWords = new MutableLiveData<>();//搜索框中的關鍵字

    public MutableLiveData<String> getSearchWords() {
        return searchWords;
    }

    private MutableLiveData<Boolean> showSearchList = new MutableLiveData<>();//是否顯示關鍵字搜索結果

    public MutableLiveData<Boolean> getShowSearchList() {
        return showSearchList;
    }


    public DBMapActivityViewModel() {

        showSearchList.setValue(false);
    }

    private boolean isHandDrag = true; //是否是手動拖動地圖
    private boolean isFirstLoadList = true; //是否是首次加載
    private boolean isSearchClick = false;
    private int eventCode;//從上一個頁面傳過來的eventcode,用於返回
    private WeakHashMap<String, Object> eventMap = new WeakHashMap<>();//通過eventbus將數據傳回去
    String hasAddress = "";
    String provLat = "";
    String provLng = "";

    public String getHasAddress() {
        return hasAddress;
    }

    public void setHasAddress(String hasAddress) {
        this.hasAddress = hasAddress;
    }

    public String getProvLat() {
        return provLat;
    }

    public void setProvLat(String provLat) {
        this.provLat = provLat;
    }

    public String getProvLng() {
        return provLng;
    }

    public void setProvLng(String provLng) {
        this.provLng = provLng;
    }

    public boolean isSearchClick() {
        return isSearchClick;
    }

    public void setSearchClick(boolean searchClick) {
        isSearchClick = searchClick;
    }

    public int getEventCode() {
        return eventCode;
    }

    public void setEventCode(int eventCode) {
        this.eventCode = eventCode;
    }

    public WeakHashMap<String, Object> getEventMap() {
        return eventMap;
    }

    public void setEventMap(WeakHashMap<String, Object> eventMap) {
        this.eventMap = eventMap;
    }

    public boolean isHandDrag() {
        return isHandDrag;
    }

    public void setHandDrag(boolean handDrag) {
        isHandDrag = handDrag;
    }

    public boolean isFirstLoadList() {
        return isFirstLoadList;
    }

    public void setFirstLoadList(boolean firstLoadList) {
        isFirstLoadList = firstLoadList;
    }

}

總結

	這個MapActivity用到了兩個adapter,一個是根據經緯度獲取附近poi聯想數據的adapter(PoiListAdapter),一個是根據用戶輸入的字符串獲取到的聯想數據(SearchPlaceListAdapter),點擊確認按鈕,將選中的item相應的數據傳回。
	有啥問題或者我哪裏有寫的不對的地方歡迎在評論區留言,行行好吧,點個贊加個關注吧,蟹蟹您了!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章