百度地图开发的笔记(篇3)高仿微信发送位置功能

在上一篇中,记录了实现这个功能时,遇到的一些问题以及解决,那么这篇就看下具体的实现代码.

该功能的思路及问题解决:

百度地图开发的笔记(篇2)高仿微信发送位置功能

主要功能(参照微信发送定位):
  • 1.定位所在位置并且展示周边POI(建筑物等信息);
  • 2.拖拽地图完成,返回中心覆盖物所处位置周边的POI信息;
  • 3.支持关键词等搜索,每次搜索完成,中央覆盖物移动到第一条POI信息的相应位置;
  • 4.点击右上角的图标,中央覆盖物回到所定位的位置;
  • 5.点击下边列表的某条数据,将中央覆盖物移至该条数据对应的位置;
  • 6.发送定位时,有相应的地图位置截图和地址信息.
代码实现:

下面核心代码, 实现功能1和功能2:

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.ddress);	
		initLocation();
		initListener();
	}
	
	private void initLocation() {
	        // 打开定位图层,显示当前位置
	        mbaiduMap.setMyLocationEnabled(true);
	
	        BitmapDescriptor mapIndicator = BitmapDescriptorFactory.fromResource(R.drawable.map_indicator);
	        MyLocationConfiguration config = new MyLocationConfiguration(
	                MyLocationConfiguration.LocationMode.FOLLOWING,     //NORMAL普通态  //COMPASS  // FOLLOWING跟随态,保持定位图标在地图中心
	                false, // 是否显示方向
	                mapIndicator);// 更换图标
	        mbaiduMap.setMyLocationConfiguration(config);
	
	        MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.zoomTo(15);
	        mbaiduMap.setMapStatus(mapStatusUpdate);
	
	        // 创建定位对象
	        mLocationClient = new LocationClient(this);
	        // 设置监听器接收结果
	        mLocationClient.registerLocationListener(new BDAbstractLocationListener() {
	            @Override	// 定位到数据回调此方法
	            public void onReceiveLocation(BDLocation location) {
	                isFirstLocation = true;
	                if (location == null) {
	                    return;
	                }
	
	                if(jobAddress != null){
	                    jobAddress.clear();
	                }
	                // 详细的地址信息
	                mCurrAddrStr = location.getAddrStr();
	                mCity = location.getCity(); 			// 城市
	                mCurrLatitude = location.getLatitude(); 	// 纬度
	                mCurrLongitude = location.getLongitude(); // 经度
	
	                initSearch();
	                refreshBaiduMap(mCurrLatitude,mCurrLongitude,radius);
	            }
	        });
	
	 }

	 private void refreshBaiduMap(double currLatitude,double currLongitude,float accuracy){
        MyLocationData datas = new MyLocationData
                .Builder()
                .latitude(currLatitude)   // 纬度
                .longitude(currLongitude)  // 经度
                .accuracy(accuracy) // 定位的精度
                .build();
        // 更新我的位置, 刷新界面显示
        mbaiduMap.setMyLocationData(datas);
    }

	@Override
    public void initListener() {
        mbaiduMap.setOnMapStatusChangeListener(new BaiduMap.OnMapStatusChangeListener() {
            @Override
            public void onMapStatusChangeStart(MapStatus mapStatus) {
            }
            @Override
            public void onMapStatusChangeStart(MapStatus mapStatus, int i) {
                Log.i("onMapStatusChangeStart,触发的类型 == " + i);
            }
            @Override
            public void onMapStatusChange(MapStatus mapStatus) {
            }
            @Override
            public void onMapStatusChangeFinish(MapStatus mapStatus) {
				//定位完成和移动回到原点时会触发
                if(isFirstLocation){//是否定位到原点
                    mapCenterLatLng = mapStatus.target;
                    getAddressData(mapCenterLatLng);

                }
            }
        });
        mbaiduMap.setOnMapTouchListener(new BaiduMap.OnMapTouchListener() {
            @Override
            public void onTouch(MotionEvent motionEvent) {
                switch(motionEvent.getAction()){
                    case MotionEvent.ACTION_UP:
                        mapCenterLatLng = mbaiduMap.getMapStatus().target;
						//获取周边POI
                        getAddressData(mapCenterLatLng);
                        break;
                }
            }
        });

        mbaiduMap.setOnMapLoadedCallback(new BaiduMap.OnMapLoadedCallback() {
            @Override
            public void onMapLoaded() {
                //地图加载完成才开始定位
                mLocationClient.start();
            }
        });
    }

	//获取周边的数据(周围的建筑物)
    private void getAddressData(LatLng latlng){
        coordinateToAddress(latlng);
    }
    //逆地理编码(即坐标转地址)
    private void coordinateToAddress(LatLng ptCenter){
        mSearch = GeoCoder.newInstance();
        OnGetGeoCoderResultListener listener = new OnGetGeoCoderResultListener() {
            //获取地理编码结果
            public void onGetGeoCodeResult(GeoCodeResult result) {
                if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
                    //没有检索到结果

                }
            }
            @Override
            public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) {
                //获取反向地理编码结果
                if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) {
                    //没有找到检索结果
                }

                List<PoiInfo> poiList = result.getPoiList();
                PoiInfo poiInfo;
				
                if(isFirstLocation) {//刚进来时,第一条显示当前位置
                    isFirstLocation = false;
                    poiInfo = new PoiInfo();
                    poiInfo.address = result.getAddress();
                    poiInfo.location = result.getLocation();
                    poiList.add(0,poiInfo);
                }
				//设置屏幕下边的ListView数据渲染
                setBaseAdater(poiList);
            }
        };
        mSearch.setOnGetGeoCodeResultListener(listener);
        mSearch.reverseGeoCode(new ReverseGeoCodeOption()
                .location(ptCenter));

    }

上面的逻辑点:

  • 需求1: 当定位监听registerLocationListener类,监听到定位信息,调用refreshBaiduMap方法显示当前位置坐标,会触发OnMapStatusChangeListener类,从而获取到周边POI;
  • 需求2: 当拖拽地图时,触发OnMapTouchListener类,在手势离开屏幕时,拿到地图中心点地理坐标,反地理编码查询周边POI;

实现功能3: 支持关键词等搜索,每次搜索完成,中央覆盖物移动到第一条POI信息的相应位置

	public void onClick(View view, int id) {
        switch(id){
            case R.id.address_search_icon:
                if(GlobalUtils.isValidClick(VALID_CLICK)){
                    search();
                }
                break;
		}
	}
	private PoiSearch mPoiSearch;
    private void initSearch() {
        // 创建搜索对象
        mPoiSearch = PoiSearch.newInstance();
        // 设置监听器
     	mPoiSearch.setOnGetPoiSearchResultListener(new OnGetPoiSearchResultListener() {
            @Override	// 接收搜索结果
            public void onGetPoiResult(PoiResult poiResult) {
                if (poiResult == null || poiResult.error == SearchResult.ERRORNO.RESULT_NOT_FOUND) {
                    if(!GlobalUtils.isOpenGps(Global.getContext())){
                        showToast(GlobalUtils.getString(R.string.usercenter_selete_address_gps_close));
                    }else{
                        if(locationTag){//如果为刚刚进行权限检测后的定位失败,应该为“定位”权限未打开
                            showNeverAskDialog();
                        }else {
                            showToast(GlobalUtils.getString(R.string.usercenter_search_no_result));
                        }
                    }
                    locationTag=false;//复位
                    return ;
                }
                setBaseAdater(poiResult.getAllPoi());

            }
            @Override  // 详情数据
            public void onGetPoiDetailResult(PoiDetailResult poiDetailResult) {
                if (poiDetailResult == null || poiDetailResult.error == SearchResult.ERRORNO.RESULT_NOT_FOUND) {
                    showToast(GlobalUtils.getString(R.string.usercenter_search_no_result));
                    return ;
                }
            }
            @Override
            public void onGetPoiIndoorResult(PoiIndoorResult poiIndoorResult) {
            }
        });

		//在线搜索
        mSuggestionSearch = SuggestionSearch.newInstance();
        MyGetSuggResultListener myGetSuggResultListener = new MyGetSuggResultListener(this);
        myGetSuggResultListener.setOnGetSuggestionResListener(new OnGetSuggestionResListener() {
            @Override
            public void getSuggestionRes(List<LocationGpsBean> res) {  
				//listView渲染数据
                setArrayAdater(res);
            }
        });
        mSuggestionSearch.setOnGetSuggestionResultListener(myGetSuggResultListener);

    }

	//调起搜索的动作
	private void search() {
        GlobalUtils.hideKeyboard(mEtInputSearch);
        String searchInput = mEtInputSearch.getText().toString().trim();
        if(TextUtils.isEmpty(searchInput)){
            showToast(GlobalUtils.getString(R.string.search_input_content_empty));
            return ;
        }
        //下面做搜寻的操作
        if(mPoiSearch == null){
            initSearch();
        }
        // 发起搜索
        if(searchInput.contains("市")){
            mIsCurrSearchAction = true;
            String[] splitInputContent = searchInput.split("市");
            int length = splitInputContent.length;
            String city= "";
            String keyword= "";
            if(length==1){          //不能周边搜索,市的名称作为key
                keyword = splitInputContent[0];
            }
            if(length>=2){
                city = splitInputContent[0];
                keyword = splitInputContent[1];
            }
            mPoiSearch.searchInCity((new PoiCitySearchOption())
                    .city(city)
                    .keyword(keyword));
            return;
        }
        mSuggestionSearch.requestSuggestion((new SuggestionSearchOption())
                .city(mCity!=null? mCity:"")            //在线搜索 == 关键词搜索
                .keyword(searchInput));

    }
	
	private List<LocationGpsBean> jobAddress = new ArrayList<>();
	
	//listView渲染数据
	private void setBaseAdater(List<PoiInfo> allPoi){
        jobAddress.clear();
        if(allPoi!=null && allPoi.size()>0) {
            if(mIsCurrSearchAction){
				MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLng(allPoi.get(0).location);
       			mbaiduMap.animateMapStatus(mapStatusUpdate);
            }
            for (PoiInfo info : allPoi) {
                LocationGpsBean bean = new LocationGpsBean();
                bean.blackName = info.name;
                bean.address = (info.address =="") ? info.name : info.address ;
                bean.uId = info.uid;
                bean.pt = info.location;
                jobAddress.add(bean);
            }
        }else{
            showToast(GlobalUtils.getString(R.string.usercenter_search_no_result));
            return;
        }
        mAdapter = new JobAddressAdapter(this, jobAddress);
        mLvAddressNews.setAdapter(mAdapter);
        mLvAddressNews.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                setSelectP(position);
            }
        });
        mAdapter.selectPosition(0);//默认第1项
        selectGpsBean = jobAddress.get(0);
        mIsCurrSearchAction = false;
    }

实现功能4: 点击右上角的图标,中央覆盖物回到所定位的位置

	//点击右上角的图标,中央覆盖物回到所定位的位置;
	 public void moveToCenter() {
        isFirstLocation = true;
		//当前定位位置坐标
        LatLng latLng = new LatLng(mCurrLatitude, mCurrLongitude);
        MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLng(latLng);
        mbaiduMap.animateMapStatus(mapStatusUpdate);
    }

实现功能5: 点击下边列表的某条数据,将中央覆盖物移至该条数据对应的位置

	//listView的事件监听
	 listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                setSelectP(position);
            }
     });
	
	private void setSelectP(int position){
        selectGpsBean = jobAddress.get(position);
        mAdapter.selectPosition(position);
        mAdapter.notifyDataSetChanged();
        mLvAddressNews.smoothScrollToPosition(position);
		//将中央覆盖物移至所点击数据对应的位置
        MapStatusUpdate mapStatusUpdate = MapStatusUpdateFactory.newLatLng(selectGpsBean.getPt());
        mbaiduMap.animateMapStatus(mapStatusUpdate);
    }

实现功能6: 发送定位时,有相应的地图位置截图和地址信息

	//点击则发送定位
	private void onSendAddress(){
		LatLng latlng = selectGpsBean.getPt();
	                    loadingDialog.show();
	                    BitmapDescriptor mapCenterPoint = BitmapDescriptorFactory.fromResource(R.drawable.location_origin_point);
	                    OverlayOptions option = new MarkerOptions()
	                                .position(new LatLng(latlng.latitude,latlng.longitude))
	                                .icon(mapCenterPoint);
	                   mbaiduMap.addOverlay(option);
	
	                    mbaiduMap.setMyLocationEnabled(false);
	                    mIvMapCenter.setVisibility(View.GONE);
						//由于图片添加marker需要一定时间,才可以显示,故这里延时500ms
						//如果不延时,截图上没有marker
	                    mBaiduMapView.postDelayed(new Runnable() {
	                       @Override
	                       public void run() {
								//截图动作
	                           mbaiduMap.snapshot(new BaiduMap.SnapshotReadyCallback() {
	                                       @Override
	                                       public void onSnapshotReady(Bitmap bitmap) 
	                                           	//上传截图
												uploadFile(bitmap);
	                                       }
	                           });
	                       }
	                   },500);

	}	

相应的布局:

	<?xml version="1.0" encoding="utf-8"?>
	<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
	    android:layout_width="match_parent"
	    android:layout_height="match_parent"
	    android:background="@color/color_gray_backgroud">
	
	    <LinearLayout
	        android:layout_width="match_parent"
	        android:layout_height="match_parent"
	        android:orientation="vertical">

	        <include layout="@layout/layout_base_item_header" />
	
	        <LinearLayout
	            android:layout_width="match_parent"
	            android:layout_height="40dp"
	            android:layout_marginLeft="20dp"
	            android:layout_marginRight="20dp"
	            android:layout_marginTop="15dp"
	            android:background="@drawable/shape_edit_myintroduction"
	            android:gravity="center_vertical"
	            android:orientation="horizontal">
	
	            <ImageView
	                android:id="@+id/address_search_icon"
	                android:layout_width="36dp"
	                android:layout_height="36dp"
	                android:clickable="true"
	                android:paddingLeft="10dp"
	                android:paddingRight="6dp"
	                android:src="@drawable/localbaidu_search" />
	
	            <!--        <item name="android:imeOptions">actionSearch</item>-->
	            <EditText
	                android:id="@+id/et_address_search_input"
	                style="@style/EditTextStyle"
	                android:layout_width="0dp"
	                android:layout_height="wrap_content"
	                android:layout_weight="1"
	                android:background="@null"
	                android:hint="搜索"
	                android:maxLength="20"
	                android:singleLine="true"
	                android:textColor="@color/text_gray_01"
	                android:textSize="@dimen/usercenter_text16_size" />
	        </LinearLayout>
	
	
	
	        <View
	            android:layout_width="match_parent"
	            android:layout_height="1dp"
	            android:layout_marginTop="10dp"
	            android:background="@color/item_line" />
	        
	        <RelativeLayout
	             android:layout_width="match_parent"
	             android:layout_height="230dp">
	                <com.baidu.mapapi.map.MapView
	                    android:id="@+id/mpv_address_baidu"
	                    android:layout_width="match_parent"
	                    android:layout_height="match_parent" />
	                <ImageView
	                    android:id="@+id/iv_map_center"
	                    android:layout_width="wrap_content"
	                    android:layout_height="wrap_content"
	                    android:src="@drawable/location_origin_point"
	                    android:layout_above="@+id/space_selete_address"
	                    android:layout_centerHorizontal="true"/>
	
					<!--这里设置占位控件space居中,是为了让上面的imageView处于地图屏幕中心偏上一点的位置,不至于和定位的图标重合-->
	                <Space
	                    android:id="@+id/space_selete_address"
	                    android:layout_height="@dimen/dimen_size_2"
	                    android:layout_width="@dimen/dimen_size_2"
	                    android:layout_centerInParent="true"/>
	                <Button
	                    android:id="@+id/btn_edit_address_center"
	                    android:layout_width="32dp"
	                    android:layout_height="32dp"
	                    android:layout_alignParentRight="true"
	                    android:layout_margin="6dp"
	                    android:background="@drawable/icon_gps"
						android:onClick="search" />
	        </RelativeLayout>
	
	        <View
	            android:layout_width="match_parent"
	            android:layout_height="1dp"
	            android:background="@color/item_line" />
	
	        <!--展示工作地点位置信息的ListView-->
	        <ListView
	            android:id="@+id/lv_usercenter_edit_selete_job_address_news"
	            android:layout_width="match_parent"
	            android:layout_height="match_parent"
	            android:background="@color/color_white"></ListView>
	    </LinearLayout>
	
	</RelativeLayout>

说明:上面xml中设置占位控件space居中,是为了让上面的imageView处于地图屏幕中心偏上一点的位置,不至于和定位的图标重合,这样就完成高仿微信发送定位功能.

链接

百度地图开发基础篇
百度地图开发的笔记(篇2)高仿微信发送位置功能

GitHub链接

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值