-
2020-08-03 11:52:14
以下内容转载自面糊的文章《模仿微信发送位置功能》
作者:面糊
链接:https://www.jianshu.com/p/47b3ada2e36d
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
前言
微信的发送位置功能是一个十分方便的功能,他会定位用户当前所在地点,然后请求用户周边的POI,并且还可以通过拖动地图来获取其他的位置发送给对方,本Demo是结合腾讯地图SDK来实现类似的功能。
使用场景
拖动地图选择地图的中心点,然后请求该点周边的门店信息,可以通过设置搜索分类来指定搜索门店的类型,如:美食、学校等。
准备
核心代码:
1、设置大头针,固定在地图中央,并监听地图移动的时候大头针跟随移动:
- (void)mapViewRegionChange:(QMapView *)mapView { // 更新位置 _annotation.coordinate = mapView.centerCoordinate; }
2、配置周边检索功能,将检索类型设置为"美食":
- (void)searchCurrentLocationWithKeyword:(NSString *)keyword { CLLocationCoordinate2D centerCoord = self.mapView.centerCoordinate; QMSPoiSearchOption *option = [[QMSPoiSearchOption alloc] init]; if (keyword.length > 0) { option.keyword = keyword; } option.boundary = [NSString stringWithFormat:@"nearby(%f,%f,2000,1)", centerCoord.latitude, centerCoord.longitude]; [option setFilter:@"category=美食"]; [self.mapSearcher searchWithPoiSearchOption:option]; }
3、解析检索结果,移动地图视野,并将结果显示在tableView上:
- (void)searchWithPoiSearchOption:(QMSPoiSearchOption *)poiSearchOption didReceiveResult:(QMSPoiSearchResult *)poiSearchResult { NSLog(@"%@", poiSearchResult); if (poiSearchResult.count == 0) { return; } // 地图移动到搜索结果的第一个位置 if (_searchBar.text.length > 0) { _selectedIndex = 0; QMSPoiData *firstData = poiSearchResult.dataArray[0]; _annotation.coordinate = firstData.location; [self.mapView setCenterCoordinate:firstData.location animated:YES]; } else { _selectedIndex = -1; } _searchResultArray = poiSearchResult.dataArray; [_searchResultTableView reloadData]; }
以上就是核心代码,在Demo中还添加了用于显示地址的TableView以及搜索位置的SearchBar,有兴趣的同学可以在文章最下方进入码云下载完整示例。
示例:搜索西二旗地铁附近的美食
链接
感兴趣的同学可以在码云中下载Demo尝试一下。
更多相关内容 -
Android-Android仿微信发送位置
2019-08-13 05:57:53Android仿微信发送位置 -
Android高德地图poi检索仿微信发送位置实例代码
2020-08-30 20:54:19本篇文章主要介绍了Android高德地图poi检索仿微信发送位置实例代码,具有一定的参考价值,有兴趣的可以了解一下。 -
仿微信发送位置
2016-11-02 18:29:02仿微信发送位置 使用高德地图实现 -
Android仿微信发送位置-百度地图
2019-01-19 18:43:49使用百度地图API,高仿微信定位。使用技术: * 百度地图的基础定位、基础地图和检索功能 * android6.0以上运行时权限 -
Android高仿微信发送位置
2016-07-14 15:35:34最近项目中有个需求是仿微信的发送位置界面,我选择了使用腾讯地图,毕竟都是腾讯的应该好仿出来,之前用百度地图实现过,不过觉得百度有点麻烦。 -
仿微信发送位置、地图选点(百度地图)
2015-10-28 16:18:50Android版仿微信发送位置、地图选点(百度地图) -
Android-Kotlin高德地图仿微信发送位置
2019-08-13 02:39:53Kotlin 高德地图 仿微信 发送位置 -
仿微信发送位置、地图选点(高德地图)
2017-12-29 11:46:07Android版仿微信发送位置、地图选点(高德地图). 前面上传过一个百度地图的, 这个也一起上传吧(捞点分, 现在下载都强制需要资源分), Key请自行申请, demo包含一个可运行apk和源码. -
Android仿微信发送位置Demo
2016-03-09 16:34:19Android 仿微信发送微信Demo Android Studio编译 -
iOS 高德地图仿微信发送实时位置
2021-01-21 20:21:07最近项目中要写一个微信那种发送位置的功能。具体功能在于: – 定位到当前位置 – 可定位当前位置附近的Poi – 可自行搜索目标位置,并展示附近的poi – 选择当前位置或者选择目标位置进行发送 一.准备工作 1.... -
Android百度地图仿微信发送位置
2020-06-18 11:01:52主要功能(参照微信发送定位): 1.定位所在位置并且展示周边POI(建筑物等信息); 2.拖拽地图完成,返回中心覆盖物所处位置周边的POI信息; 3.支持关键词等搜索,每次搜索完成,中央覆盖物移动到第一条POI信息的相应...先上图
前提:有百度地图账号并配置了相关环境,可以参考百度地图开发者文档并下载so和jar
代码有相对应的注释,关键的就是百度地图移动版开发密钥、正确填写SHA1 和 程序包名,这将影响百度地图的功能使用主要功能(参照微信发送定位):
1.定位所在位置并且展示周边POI(建筑物等信息);
2.拖拽地图完成,返回中心覆盖物所处位置周边的POI信息;
3.支持关键词等搜索,每次搜索完成,中央覆盖物移动到第一条POI信息的相应位置;
4.点击定位的图标,中央覆盖物回到所定位的位置;
5.点击下边列表的某条数据,将中央覆盖物移至该条数据对应的位置;
6.发送定位时,有相应的地图位置截图和地址信息.
————————————————核心代码
//点击地图的监听,并显示所点击位置周围的poi信息 mBaiduMap.setOnMapClickListener(new BaiduMap.OnMapClickListener() { @Override public void onMapClick(LatLng latLng) { mBaiduMap.clear(); adapter.changeSelected(0); mJARecyclerView.smoothScrollToPosition(0); MapStatusUpdate u = MapStatusUpdateFactory .newLatLng(latLng); mBaiduMap.animateMapStatus(u); isUseGeoCoder = true; } @Override public boolean onMapPoiClick(MapPoi mapPoi) { LatLng position = mapPoi.getPosition(); mBaiduMap.clear(); MapStatusUpdate u = MapStatusUpdateFactory .newLatLng(position); mBaiduMap.animateMapStatus(u); isUseGeoCoder = true; return true; } });
//移动地图的监听,并显示所点击位置周围的poi信息 mBaiduMap.setOnMapTouchListener(new BaiduMap.OnMapTouchListener() { @Override public void onTouch(MotionEvent motionEvent) { if (motionEvent.getAction() == MotionEvent.ACTION_UP) { isUseGeoCoder = true; isNeedAnimation = true; } } });
//地图状态发生改变的监听,不管是点击还是移动地图,都会触发状态改变的监听,处理位置居中显示,开启动画,反地理编码(根据坐标获取位置名称、地址等信息) mBaiduMap.setOnMapStatusChangeListener(new BaiduMap.OnMapStatusChangeListener() { @Override public void onMapStatusChangeStart(MapStatus mapStatus) { } @Override public void onMapStatusChangeStart(MapStatus mapStatus, int i) { } @Override public void onMapStatusChange(MapStatus mapStatus) { } @Override public void onMapStatusChangeFinish(MapStatus mapStatus) { mBaiduMap.clear(); if (isNeedAnimation) { centerImage.startAnimation(centerAnimation); } LatLng target = mapStatus.target; if (isUseGeoCoder) { showLoading(true); mGeoCoder.reverseGeoCode((new ReverseGeoCodeOption()) .location(target)); adapter.changeSelected(0); mJARecyclerView.smoothScrollToPosition(0); } } });
完整代码:
SelectAddressActivity.classpackage com.lyw.myproject.baidumap.cityselect; import android.content.Context; import android.graphics.Point; import android.os.Bundle; import android.text.Editable; import android.text.Spannable; import android.text.SpannableStringBuilder; import android.text.TextWatcher; import android.text.style.ForegroundColorSpan; import android.util.Log; import android.view.MotionEvent; import android.view.View; import android.view.animation.Animation; import android.view.animation.AnimationUtils; import android.view.animation.LinearInterpolator; import android.view.animation.RotateAnimation; import android.view.inputmethod.InputMethodManager; import android.widget.EditText; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import com.baidu.location.BDLocation; import com.baidu.location.BDLocationListener; import com.baidu.location.LocationClient; import com.baidu.location.LocationClientOption; import com.baidu.mapapi.map.BaiduMap; import com.baidu.mapapi.map.MapPoi; import com.baidu.mapapi.map.MapStatus; import com.baidu.mapapi.map.MapStatusUpdate; import com.baidu.mapapi.map.MapStatusUpdateFactory; import com.baidu.mapapi.map.MapView; import com.baidu.mapapi.map.MyLocationConfiguration; import com.baidu.mapapi.map.MyLocationData; import com.baidu.mapapi.map.offline.MKOLSearchRecord; import com.baidu.mapapi.map.offline.MKOfflineMap; import com.baidu.mapapi.map.offline.MKOfflineMapListener; import com.baidu.mapapi.model.LatLng; import com.baidu.mapapi.search.core.PoiInfo; import com.baidu.mapapi.search.core.SearchResult; import com.baidu.mapapi.search.geocode.GeoCodeResult; import com.baidu.mapapi.search.geocode.GeoCoder; import com.baidu.mapapi.search.geocode.OnGetGeoCoderResultListener; import com.baidu.mapapi.search.geocode.ReverseGeoCodeOption; import com.baidu.mapapi.search.geocode.ReverseGeoCodeResult; import com.baidu.mapapi.search.sug.OnGetSuggestionResultListener; import com.baidu.mapapi.search.sug.SuggestionResult; import com.baidu.mapapi.search.sug.SuggestionSearch; import com.baidu.mapapi.search.sug.SuggestionSearchOption; import com.lyw.myproject.BaseActivity; import com.lyw.myproject.BuildConfig; import com.lyw.myproject.R; import com.lyw.myproject.adapter.AddressSelectAdapter; import com.lyw.myproject.utils.PermissionUtil; import com.lyw.myproject.utils.StatusBarUtils; import com.lyw.myproject.widget.DefaultItemDecoration; import java.util.ArrayList; import java.util.List; import androidx.annotation.Nullable; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; /** * 功能描述:地址选择 * Created on 2020/6/17. * @author lyw */ public class SelectAddressActivity extends BaseActivity implements AddressSelectAdapter.OnAddressSelectItemClickListener{ private RecyclerView mJARecyclerView; private TextView cancleTv,searchAddressTv,confirmTv,searchNoDataTv; private MapView mBmapView; private EditText mSearchAddressEt; private LinearLayout searchNoDataLayout,searchNonmalLayout,searchEditLayout; private ImageView centerImage,locationIv,clearInputIv,mCheckTipIv; private BaiduMap mBaiduMap; private LocationClient mLocationClient; //是否首次定位 boolean isFirstLoc = true; private AddressSelectAdapter adapter; private List<PoiInfo> mFilterList = new ArrayList<>(); //选择的位置信息 private PoiInfo selPoiDetailInfo; // 当前经纬度 double mLantitude; double mLongtitude; LatLng mLoactionLatLng; // MapView中央对于的屏幕坐标 Point mCenterPoint = null; // 地理编码 GeoCoder mGeoCoder = null; List<PoiInfo> mInfoList; PoiInfo mCurentInfo; MyBDLocationListner mListner = null; private Animation centerAnimation; //是否使用反地理编码 private boolean isUseGeoCoder = true; //是否需要动画 private boolean isNeedAnimation = true; private InputMethodManager inputMethodManager; private SuggestionSearch mSuggestionSearch; private String changeContent; private MKOfflineMap mOffline; //选中的CityCode private String selectCityCode; private ArrayList<MKOLSearchRecord> mkolSearchRecords; private RotateAnimation mAnimation; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_activity_address_select_layout); FullscreenInputWorkaroundUtil.assistActivity(this); //设置状态栏透明 StatusBarUtils.makeStatusBarTransparent(SelectAddressActivity.this); //请求位置权限 if (!PermissionUtil.isHasLocationPermission(this)) { PermissionUtil.requestLocationPermission(this); } initView(); initEvent(); inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); //得到城市code mOffline = new MKOfflineMap(); mOffline.init(new MKOfflineMapListener() { @Override public void onGetOfflineMapState(int i, int i1) { } }); } @Override public void onResume() { super.onResume(); if (mBmapView != null) { mBmapView.onResume(); } } @Override protected void onPause() { super.onPause(); if (mBmapView != null) { mBmapView.onPause(); } } @Override protected void onDestroy() { super.onDestroy(); if (mBmapView != null) { mBmapView.onDestroy(); } mBaiduMap.setMyLocationEnabled(false); if (mLocationClient != null) { mLocationClient.stop(); } if (mGeoCoder != null) { mGeoCoder.destroy(); } if (mSuggestionSearch != null) { mSuggestionSearch.destroy(); } if (mOffline != null) { mOffline.destroy(); } } private void initView() { mJARecyclerView = (RecyclerView)findViewById(R.id.recyclerview); cancleTv = (TextView)findViewById(R.id.cancle_tv); searchAddressTv = (TextView)findViewById(R.id.search_address_tv); confirmTv = (TextView)findViewById(R.id.confirm_tv); mBmapView = (MapView)findViewById(R.id.bmapView); mSearchAddressEt = (EditText)findViewById(R.id.search_address_et); searchNoDataTv = (TextView)findViewById(R.id.search_no_data_tv); searchNoDataLayout = (LinearLayout)findViewById(R.id.search_no_data_layout); searchNonmalLayout = (LinearLayout)findViewById(R.id.search_nonmal_layout); searchEditLayout = (LinearLayout)findViewById(R.id.search_edit_layout); centerImage = (ImageView)findViewById(R.id.center_image); locationIv = (ImageView)findViewById(R.id.location_iv); clearInputIv = (ImageView)findViewById(R.id.clear_input_iv); mCheckTipIv = (ImageView)findViewById(R.id.check_tip_iv); } private void initEvent() { mBaiduMap = mBmapView.getMap(); adapter = new AddressSelectAdapter(this); adapter.setOnAddressSelectItemClickListener(this); mJARecyclerView.setLayoutManager(new LinearLayoutManager(this)); mJARecyclerView.addItemDecoration(new DefaultItemDecoration(this, R.dimen.common_utils_divider_height, R.color.src_line_c9)); mJARecyclerView.setAdapter(adapter); mSearchAddressEt.setHint("搜索地点"); searchAddressTv.setText("搜索地点"); mSearchAddressEt.addTextChangedListener(new SearchDevicesTextWatcher()); cancleTv.setText("取消"); confirmTv.setText("确定"); //加载动画 mAnimation = new RotateAnimation(0, 359, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); mAnimation.setDuration(1000); mAnimation.setRepeatCount(-1); mAnimation.setInterpolator(new LinearInterpolator()); mCheckTipIv.setColorFilter(getResources().getColor(R.color.src_c1)); mCheckTipIv.setImageResource(R.mipmap.icon_login_loading); centerAnimation = AnimationUtils.loadAnimation(this, R.anim.center_anim); initMyLocation(); mBaiduMap.setCompassEnable(false); searchNonmalLayout.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { searchNonmalLayout.setVisibility(View.GONE); searchEditLayout.setVisibility(View.VISIBLE); showInput(mSearchAddressEt); } }); clearInputIv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { searchNonmalLayout.setVisibility(View.VISIBLE); searchEditLayout.setVisibility(View.GONE); mSearchAddressEt.setText(""); mSearchAddressEt.clearFocus(); hideSoftInputWindow(v); mFilterList.clear(); if (mLoactionLatLng != null) { MapStatus.Builder builder = new MapStatus.Builder(); builder.target(mLoactionLatLng).zoom(17.0f); mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus (builder.build())); isUseGeoCoder = true; isNeedAnimation = false; } else { } } }); locationIv.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mLoactionLatLng != null) { MapStatus.Builder builder = new MapStatus.Builder(); builder.target(mLoactionLatLng).zoom(17.0f); mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus (builder.build())); isUseGeoCoder = true; isNeedAnimation = true; } else { } } }); } /** * 隐藏键盘 */ private void hideSoftInputWindow(View view) { if (inputMethodManager.isActive()) { inputMethodManager.hideSoftInputFromWindow(view.getWindowToken(), 0); } } /** * 显示键盘 * @param et 输入焦点 */ public void showInput(final EditText et) { et.requestFocus(); if (inputMethodManager.isActive()) { inputMethodManager.showSoftInput(et, InputMethodManager.SHOW_IMPLICIT); } } /** * 获取我的定位 */ private void initMyLocation() { // 初始化地图 mBmapView.showZoomControls(false); MapStatusUpdate msu = MapStatusUpdateFactory.zoomTo(17.0f); mBaiduMap.setMapStatus(msu); mInfoList = new ArrayList<PoiInfo>(); mCenterPoint = mBaiduMap.getMapStatus().targetScreen; mLoactionLatLng = mBaiduMap.getMapStatus().target; // 定位 mBaiduMap.setMyLocationEnabled(true); mLocationClient = new LocationClient(this); mListner = new MyBDLocationListner(); mLocationClient.registerLocationListener(mListner); LocationClientOption option = new LocationClientOption(); option.setCoorType("bd09ll"); mLocationClient.setLocOption(option); mLocationClient.start(); // 地理编码 mGeoCoder = GeoCoder.newInstance(); mGeoCoder.setOnGetGeoCodeResultListener(mGeoListener); showLoading(true); mBaiduMap.setOnMapClickListener(new BaiduMap.OnMapClickListener() { @Override public void onMapClick(LatLng latLng) { mBaiduMap.clear(); adapter.changeSelected(0); mJARecyclerView.smoothScrollToPosition(0); MapStatusUpdate u = MapStatusUpdateFactory .newLatLng(latLng); mBaiduMap.animateMapStatus(u); isUseGeoCoder = true; } @Override public boolean onMapPoiClick(MapPoi mapPoi) { LatLng position = mapPoi.getPosition(); mBaiduMap.clear(); MapStatusUpdate u = MapStatusUpdateFactory .newLatLng(position); mBaiduMap.animateMapStatus(u); isUseGeoCoder = true; return true; } }); mBaiduMap.setOnMapTouchListener(new BaiduMap.OnMapTouchListener() { @Override public void onTouch(MotionEvent motionEvent) { if (motionEvent.getAction() == MotionEvent.ACTION_UP) { isUseGeoCoder = true; isNeedAnimation = true; } } }); mBaiduMap.setOnMapStatusChangeListener(new BaiduMap.OnMapStatusChangeListener() { @Override public void onMapStatusChangeStart(MapStatus mapStatus) { } @Override public void onMapStatusChangeStart(MapStatus mapStatus, int i) { } @Override public void onMapStatusChange(MapStatus mapStatus) { } @Override public void onMapStatusChangeFinish(MapStatus mapStatus) { mBaiduMap.clear(); if (isNeedAnimation) { centerImage.startAnimation(centerAnimation); } LatLng target = mapStatus.target; if (isUseGeoCoder) { showLoading(true); mGeoCoder.reverseGeoCode((new ReverseGeoCodeOption()) .location(target)); adapter.changeSelected(0); mJARecyclerView.smoothScrollToPosition(0); } } }); mSuggestionSearch = SuggestionSearch.newInstance(); mSuggestionSearch.setOnGetSuggestionResultListener(listener); } OnGetSuggestionResultListener listener = new OnGetSuggestionResultListener() { @Override public void onGetSuggestionResult(SuggestionResult suggestionResult) { //处理sug检索结果 List<SuggestionResult.SuggestionInfo> allSuggestions = suggestionResult.getAllSuggestions(); mInfoList.clear(); if (allSuggestions == null) { }else { for (SuggestionResult.SuggestionInfo suggestionInfo : allSuggestions) { if (suggestionInfo == null) { continue; } PoiInfo info = new PoiInfo(); info.address = suggestionInfo.getKey(); LatLng pt = suggestionInfo.pt; info.location = pt; info.city = suggestionInfo.city; info.name = suggestionInfo.getKey(); mInfoList.add(info); } selPoiDetailInfo = mInfoList.get(0); mkolSearchRecords = mOffline.searchCity(selPoiDetailInfo.getCity()); selectCityCode = String.valueOf(mkolSearchRecords.get(0).cityID); } handleRelativeAddressResult(mInfoList, changeContent); } }; @Override public void onAddressSelectItemClick(PoiInfo info, int position) { isUseGeoCoder = false; isNeedAnimation = true; mBaiduMap.clear(); LatLng la = info.location; MapStatusUpdate u = MapStatusUpdateFactory.newLatLng(la); mBaiduMap.animateMapStatus(u); selPoiDetailInfo = info; adapter.changeSelected(position); if (position != 0) { mkolSearchRecords = mOffline.searchCity(selPoiDetailInfo.getCity()); selectCityCode = String.valueOf(mkolSearchRecords.get(0).cityID); } if (BuildConfig.DEBUG) { Log.d("lyw", "onAddressSelectItemClick-cityCode->" + info.city+selectCityCode); } } // 定位监听器 private class MyBDLocationListner implements BDLocationListener { @Override public void onReceiveLocation(BDLocation location) { if (location == null || mBmapView == null){ return; } if (isFirstLoc) { MyLocationData data = new MyLocationData.Builder() .accuracy(location.getRadius()) .latitude(location.getLatitude()) .longitude(location.getLongitude()) .build(); mBaiduMap.setMyLocationData(data); MyLocationConfiguration config = new MyLocationConfiguration( MyLocationConfiguration.LocationMode.NORMAL, false, null); mBaiduMap.setMyLocationConfigeration(config); mLantitude = location.getLatitude(); mLongtitude = location.getLongitude(); LatLng currentLatLng = new LatLng(mLantitude, mLongtitude); mLoactionLatLng = new LatLng(mLantitude, mLongtitude); isFirstLoc = false; MapStatusUpdate u = MapStatusUpdateFactory .newLatLng(currentLatLng); mBaiduMap.animateMapStatus(u); mGeoCoder.reverseGeoCode((new ReverseGeoCodeOption()) .location(currentLatLng)); } } } /** * 地理编码监听器 */ OnGetGeoCoderResultListener mGeoListener = new OnGetGeoCoderResultListener() { @Override public void onGetGeoCodeResult(GeoCodeResult result) { } @Override public void onGetReverseGeoCodeResult(ReverseGeoCodeResult result) { if (BuildConfig.DEBUG) { Log.d("lyw","result.error-->" + result.error); } if (result == null || result.error != SearchResult.ERRORNO.NO_ERROR) { if (result.error == SearchResult.ERRORNO.NETWORK_ERROR) { showLoading(false); Toast.makeText(SelectAddressActivity.this,"网络异常",Toast.LENGTH_SHORT).show(); } } else { showLoading(false); mCurentInfo = new PoiInfo(); mCurentInfo.address = result.getAddress(); mCurentInfo.location = result.getLocation(); mCurentInfo.name = result.getAddress(); mCurentInfo.city = String.valueOf(result.getCityCode()); selectCityCode = String.valueOf(result.getCityCode()); mInfoList.clear(); mInfoList.add(mCurentInfo); if (result.getPoiList() != null) { mInfoList.addAll(result.getPoiList()); } adapter.setPoiAddrList(mInfoList); adapter.notifyDataSetChanged(); selPoiDetailInfo = mInfoList.get(0); } } }; class SearchDevicesTextWatcher implements TextWatcher { @Override public void beforeTextChanged(CharSequence charSequence, int start, int count, int before) { } @Override public void onTextChanged(CharSequence charSequence, int start, int before, int count) { changeContent = charSequence.toString(); if (changeContent != null && !changeContent.isEmpty() || !"".equals(changeContent)) { mSuggestionSearch.requestSuggestion(new SuggestionSearchOption().city("中国").keyword(changeContent)); }else { if (mLoactionLatLng != null) { MapStatus.Builder builder = new MapStatus.Builder(); builder.target(mLoactionLatLng).zoom(17.0f); mBaiduMap.animateMapStatus(MapStatusUpdateFactory.newMapStatus (builder.build())); isUseGeoCoder = true; isNeedAnimation = false; } else { } } } @Override public void afterTextChanged(Editable editable) { } } /** * 处理搜索地点结果 * * @param mInfoList */ private void handleRelativeAddressResult(List<PoiInfo> mInfoList, String content) { mJARecyclerView.setAdapter(adapter); adapter.setPoiAddrList(mInfoList); if (mInfoList.size() == 0) { searchNoDataLayout.setVisibility(View.VISIBLE); String formatContent = String.format("没有找到“%1$s”相关内容", content); SpannableStringBuilder builder = new SpannableStringBuilder(formatContent); ForegroundColorSpan blueSpan = new ForegroundColorSpan(getResources().getColor(R.color.src_text_c16)); int start = formatContent.indexOf(content); int end = start + content.length(); builder.setSpan(blueSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); searchNoDataTv.setText(builder); } else { searchNoDataLayout.setVisibility(View.GONE); } } /** * Loading的显示 * @param isShowLoading */ private void showLoading(final boolean isShowLoading){ runOnUiThread(new Runnable() { @Override public void run() { if (isShowLoading) { mCheckTipIv.setVisibility(View.VISIBLE); mCheckTipIv.setImageResource(R.mipmap.icon_login_loading); mCheckTipIv.setAnimation(mAnimation); mCheckTipIv.getAnimation().start(); }else { mCheckTipIv.clearAnimation(); mCheckTipIv.setVisibility(View.GONE); } } }); } }
main_activity_address_select_layout.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent"> <com.baidu.mapapi.map.MapView android:id="@+id/bmapView" android:layout_width="match_parent" android:layout_height="match_parent" android:clickable="true" /> <ImageView android:layout_gravity="center" android:id="@+id/center_image" android:layout_width="40dp" android:layout_marginBottom="15dp" android:layout_height="40dp" android:src="@mipmap/icon_positioning" /> <ImageView android:id="@+id/location_iv" android:layout_gravity="center|end" android:layout_width="50dp" android:layout_height="50dp" android:layout_marginEnd="10dp" android:src="@mipmap/icon_map_locate" /> <RelativeLayout android:background="@drawable/background_gradient" android:paddingTop="35dp" android:paddingBottom="40dp" android:paddingStart="10dp" android:paddingEnd="10dp" android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/cancle_tv" android:textColor="@color/src_white" android:gravity="center" android:layout_width="60dp" android:layout_height="30dp"/> <TextView android:id="@+id/confirm_tv" android:layout_alignParentEnd="true" android:background="@color/src_c46" android:gravity="center" android:textColor="@color/src_white" android:layout_width="60dp" android:layout_height="30dp"/> </RelativeLayout> <LinearLayout android:orientation="vertical" android:background="@color/common_utils_white" android:layout_gravity="bottom" android:layout_width="match_parent" android:layout_height="250dp"> <LinearLayout android:id="@+id/search_nonmal_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="15dp" android:layout_marginTop="15dp" android:layout_marginEnd="15dp" android:layout_marginBottom="6dp" android:orientation="horizontal"> <LinearLayout android:gravity="center" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/common_utils_shape_address_input_white_bg" android:focusable="true" android:focusableInTouchMode="true" android:orientation="horizontal" android:paddingTop="7dp" android:paddingBottom="7dp"> <ImageView android:layout_width="18dp" android:layout_height="18dp" android:layout_gravity="center_vertical" android:layout_marginStart="13dp" android:src="@mipmap/icon_search_1"/> <TextView android:layout_marginStart="10dp" android:id="@+id/search_address_tv" android:layout_width="wrap_content" android:layout_height="wrap_content"> </TextView> </LinearLayout> </LinearLayout> <!-- 搜索 --> <LinearLayout android:visibility="gone" android:id="@+id/search_edit_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginStart="15dp" android:layout_marginTop="10dp" android:layout_marginEnd="15dp" android:layout_marginBottom="6dp" android:orientation="horizontal"> <LinearLayout android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:background="@drawable/common_utils_shape_address_input_white_bg" android:focusable="true" android:focusableInTouchMode="true" android:orientation="horizontal" android:paddingTop="7dp" android:paddingBottom="7dp"> <ImageView android:layout_width="18dp" android:layout_height="18dp" android:layout_gravity="center_vertical" android:layout_marginStart="13dp" android:src="@mipmap/icon_search_1"/> <EditText android:id="@+id/search_address_et" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_gravity="center_vertical" android:layout_marginStart="17dp" android:layout_weight="1" android:background="@null" android:maxLength="32" android:maxLines="1" android:singleLine="true" android:textColor="@color/src_text_c1" android:textColorHint="@color/src_text_c2" android:textSize="@dimen/common_utils_font_14"/> <ImageView android:id="@+id/clear_input_iv" android:layout_width="20dp" android:layout_height="20dp" android:layout_gravity="end|center_vertical" android:layout_marginEnd="13dp" android:src="@mipmap/icon_clear_enter_1"/> </LinearLayout> </LinearLayout> <androidx.recyclerview.widget.RecyclerView android:layout_below="@+id/search_devices_layout" android:id="@+id/recyclerview" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="2dp" /> <LinearLayout android:layout_below="@+id/search_devices_layout" android:layout_gravity="center" android:gravity="center" android:id="@+id/search_no_data_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/common_utils_white" android:orientation="vertical" android:visibility="gone"> <TextView android:id="@+id/search_no_data_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:layout_marginTop="20dp" android:textColor="@color/src_text_c2" android:textSize="14sp"/> </LinearLayout> </LinearLayout> <ImageView android:id="@+id/check_tip_iv" android:layout_width="40dp" android:layout_height="40dp" android:layout_marginBottom="75dp" android:layout_gravity="center|bottom" android:src="@mipmap/icon_login_loading" /> </FrameLayout>
background_gradient.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <!--实现应用背景颜色渐变--> <gradient android:startColor="@color/src_nvr" android:endColor="@color/common_utils_transparent" android:angle="270"/> </shape>
common_utils_shape_address_input_white_bg.xml
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android"> <solid android:color="@color/baidu_serach_address_bg" /> <stroke android:width="0.5dp" android:color="@color/common_utils_black_30_transparent" /> <corners android:radius="5dp" /> </shape>
AddressSelectAdapter.class
package com.lyw.myproject.adapter; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.baidu.mapapi.search.core.PoiInfo; import com.lyw.myproject.R; import java.util.ArrayList; import java.util.List; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; /** * 功能描述:位置选择Adapter * Created on 2020/4/27. * @author lyw */ public class AddressSelectAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { public Context mContext; private List<PoiInfo> infoList; private OnAddressSelectItemClickListener mItemClickListener; private int selectedPosition = 0;// 选中的位置 public AddressSelectAdapter(Context context) { mContext = context; infoList = new ArrayList<>(); } public void changeSelected(int positon){ if(positon != selectedPosition){ selectedPosition = positon; notifyDataSetChanged(); } } @Override public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) { return new MyViewHolder(LayoutInflater.from(mContext).inflate(R.layout.main_item_poi_address,viewGroup,false)); } @Override public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) { MyViewHolder hodler = (MyViewHolder) viewHolder; PoiInfo info = infoList.get(i); hodler.nameTv.setText(info.getName()); hodler.addressTv.setText(info.getAddress()); if (selectedPosition == i) { hodler.checkImageIv.setImageResource(R.mipmap.icon_select_address); }else { hodler.checkImageIv.setImageResource(0); } } @Override public int getItemCount() { return infoList.size(); } class MyViewHolder extends RecyclerView.ViewHolder{ TextView nameTv; TextView addressTv; ImageView checkImageIv; LinearLayout addressSelectItemLl; public MyViewHolder(@NonNull View itemView) { super(itemView); nameTv = (TextView)itemView.findViewById(R.id.name_tv); addressTv = (TextView)itemView.findViewById(R.id.address_tv); checkImageIv = (ImageView)itemView.findViewById(R.id.check_image_iv); addressSelectItemLl = (LinearLayout)itemView.findViewById(R.id.address_select_item_ll); addressSelectItemLl.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (mItemClickListener != null) { int posotion = getAdapterPosition(); mItemClickListener.onAddressSelectItemClick(infoList.get(posotion), posotion); } } }); } } public void setPoiAddrList(List<PoiInfo> infos){ infoList = infos; } public void clearPoiAddrList(){ infoList.clear(); } public interface OnAddressSelectItemClickListener{ void onAddressSelectItemClick(PoiInfo info, int position); } public void setOnAddressSelectItemClickListener(OnAddressSelectItemClickListener listener){ mItemClickListener = listener; } }
main_item_poi_address.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/address_select_item_ll" android:layout_width="match_parent" android:padding="10dp" android:layout_height="wrap_content" android:orientation="horizontal"> <LinearLayout android:layout_marginStart="10dp" android:orientation="vertical" android:layout_width="0dp" android:layout_weight="10" android:layout_height="wrap_content"> <TextView android:textSize="16sp" android:id="@+id/name_tv" android:textColor="@color/src_black" android:layout_width="wrap_content" android:layout_height="20dp"/> <TextView android:textSize="14sp" android:id="@+id/address_tv" android:layout_width="wrap_content" android:layout_height="match_parent"/> </LinearLayout> <LinearLayout android:layout_gravity="center" android:layout_weight="1" android:layout_margin="5dp" android:layout_width="0dp" android:layout_height="wrap_content"> <ImageView android:id="@+id/check_image_iv" android:layout_width="0dp" android:layout_weight="1" android:layout_height="20dp"/> </LinearLayout> </LinearLayout>
DefaultItemDecoration.class
package com.lyw.myproject.widget; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.view.View; import androidx.annotation.ColorRes; import androidx.annotation.DimenRes; import androidx.recyclerview.widget.RecyclerView; /** * Created on 2018/10/13. * * @author lyw **/ public class DefaultItemDecoration extends RecyclerView.ItemDecoration { private int mDivideHeight; private int mPaddingLeft; private int mPaddingRight; private Paint paint; public DefaultItemDecoration(Context context, @DimenRes int divideHeight, @ColorRes int divideColor) { this(context, divideHeight, divideColor, 0, 0); } public DefaultItemDecoration(Context context, @DimenRes int divideHeight, @ColorRes int divideColor, @DimenRes int paddingLeft, @DimenRes int paddingRight) { mDivideHeight = context.getResources().getDimensionPixelSize(divideHeight); if (paddingRight != 0) { mPaddingRight = context.getResources().getDimensionPixelSize(paddingRight); } if (paddingLeft != 0) { mPaddingLeft = context.getResources().getDimensionPixelSize(paddingLeft); } paint = new Paint(Paint.ANTI_ALIAS_FLAG); paint.setColor(context.getResources().getColor(divideColor)); } @Override public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) { super.onDraw(c, parent, state); int childCount = parent.getChildCount(); int width = parent.getWidth(); int top; int bottom; for (int i = 0; i < childCount; i++) { View childAt = parent.getChildAt(i); top = childAt.getBottom(); bottom = top + mDivideHeight; c.drawRect(mPaddingLeft, top, width - mPaddingRight, bottom, paint); } } @Override public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); outRect.bottom = mDivideHeight; } }
PermissionUtil.class
package com.lyw.myproject.utils; import android.Manifest; import android.app.Activity; import android.content.Context; import android.content.pm.PackageManager; import android.os.Build; import androidx.core.app.ActivityCompat; /** * Created by lyw on 2017/6/12. */ public class PermissionUtil { /** * 请求地理位置 * * @param context */ public static void requestLocationPermission(Context context) { if (Build.VERSION.SDK_INT >= 23) { if (!isHasLocationPermission(context)) { ActivityCompat.requestPermissions((Activity) context, PermissionManager.PERMISSION_LOCATION, PermissionManager.REQUEST_LOCATION); } } } /** * 判断是否有地理位置 * * @param context * @return */ public static boolean isHasLocationPermission(Context context) { return ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED; } }
PermissionManager.class
package com.lyw.myproject.utils; import android.Manifest; /** * Created by lyw on 2017/5/17. */ public final class PermissionManager { /** * sd卡 */ public static final int REQUEST_SD_WRITE = 101; /** * 地理位置 */ public static final int REQUEST_LOCATION = 102; /** * 相机 */ public static final int REQUEST_CAMERA = 103; /** * 录音 */ public static final int REQUEST_RECORD = 104; /** * 读取手机 */ public static final int REQUEST_READ_PHONE = 105; /** * 悬浮窗通知 */ public static final int REQUEST_ALERT_WINDOW = 106; /** * 读取MEDIA权限 */ public static final int REQUEST_READ_MEDIA = 107; /** * Android Q(10) 读取MEDIA权限 */ public static final String[] PERMISSION_READ_MEDIA = new String[]{"android.permission.READ_MEDIA_IMAGES","android.permission.READ_MEDIA_VIDEO","android.permission.READ_MEDIA_AUDIO"}; public static final String[] PERMISSION_SD_WRITE = new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}; public static final String[] PERMISSION_LOCATION = new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION}; public static final String[] PERMISSION_CAMERA = new String[]{Manifest.permission.CAMERA}; public static final String[] PERMISSION_RECORD = new String[]{Manifest.permission.RECORD_AUDIO}; public static final String[] PERMISSION_READ_PHONE = new String[]{Manifest.permission.READ_PHONE_STATE}; }
StatusBarUtils.class
package com.lyw.myproject.utils; import android.app.Activity; import android.app.Dialog; import android.graphics.Color; import android.os.Build; import android.view.View; import android.view.Window; import android.view.WindowManager; /** * Created by Administrator on 2017/7/6. * 状态栏相关工具 */ public class StatusBarUtils { public static void setWindowStatusBarColor(Activity activity, int colorResId) { try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Window window = activity.getWindow(); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.setStatusBarColor(activity.getResources().getColor(colorResId)); //底部导航栏 //window.setNavigationBarColor(activity.getResources().getColor(colorResId)); } } catch (Exception e) { e.printStackTrace(); } } public static void setWindowStatusBarColor(Dialog dialog, int colorResId) { try { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { Window window = dialog.getWindow(); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); window.setStatusBarColor(dialog.getContext().getResources().getColor(colorResId)); //底部导航栏 //window.setNavigationBarColor(activity.getResources().getColor(colorResId)); } } catch (Exception e) { e.printStackTrace(); } } public static void makeStatusBarTransparent(Activity activity) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { return; } Window window = activity.getWindow(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); int option = window.getDecorView().getSystemUiVisibility() | View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN; window.getDecorView().setSystemUiVisibility(option); window.setStatusBarColor(Color.TRANSPARENT); } else { window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); } } }
center_anim.xml
<?xml version="1.0" encoding="utf-8"?> <translate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="500" android:fillBefore="true" android:fromXDelta="0" android:fromYDelta="0" android:interpolator="@android:anim/accelerate_decelerate_interpolator" android:toXDelta="0" android:toYDelta="-100"> </translate>
FullscreenInputWorkaroundUtil.class
package com.lyw.myproject.utils; import android.app.Activity; import android.graphics.Rect; import android.view.View; import android.view.ViewTreeObserver; import android.widget.FrameLayout; /** * 功能描述:解决状态栏沉浸式,软键盘遮住布局的问题 * Created on 2020/6/18. * * @author lyw */ public class FullscreenInputWorkaroundUtil { public static void assistActivity(Activity activity) { new FullscreenInputWorkaroundUtil(activity); } private View mChildOfContent; private int usableHeightPrevious; private FrameLayout.LayoutParams frameLayoutParams; private FullscreenInputWorkaroundUtil(Activity activity) { FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content); mChildOfContent = content.getChildAt(0); mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { possiblyResizeChildOfContent(); } }); frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams(); } private void possiblyResizeChildOfContent() { int usableHeightNow = computeUsableHeight(); if (usableHeightNow != usableHeightPrevious) { int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight(); int heightDifference = usableHeightSansKeyboard - usableHeightNow; if (heightDifference > (usableHeightSansKeyboard / 4)) { frameLayoutParams.height = usableHeightSansKeyboard - heightDifference; } else { frameLayoutParams.height = usableHeightSansKeyboard; } mChildOfContent.requestLayout(); usableHeightPrevious = usableHeightNow; } } private int computeUsableHeight() { Rect r = new Rect(); mChildOfContent.getWindowVisibleDisplayFrame(r); return (r.bottom - r.top); } }
-
android仿微信发送当前位置实例源码
2016-02-23 08:50:27仿微信发送在百度地图中定位到当前位置并实现发送位置信息(经纬度,位置信息)的功能。 -
腾讯地图仿微信发送位置功能
2020-08-04 12:08:19以下内容转载自面糊的文章《模仿微信发送位置功能》 作者:面糊 链接:https://www.jianshu.com/p/47b3ada2e36d 来源:简书 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 前言 微信的...以下内容转载自面糊的文章《模仿微信发送位置功能》
作者:面糊
链接:https://www.jianshu.com/p/47b3ada2e36d
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
前言
微信的发送位置功能是一个十分方便的功能,他会定位用户当前所在地点,然后请求用户周边的POI,并且还可以通过拖动地图来获取其他的位置发送给对方,本Demo是结合腾讯地图SDK来实现类似的功能。
使用场景
拖动地图选择地图的中心点,然后请求该点周边的门店信息,可以通过设置搜索分类来指定搜索门店的类型,如:美食、学校等。
准备
核心代码:
1、设置大头针,固定在地图中央,并监听地图移动的时候大头针跟随移动:
- (void)mapViewRegionChange:(QMapView *)mapView { // 更新位置 _annotation.coordinate = mapView.centerCoordinate; }
2、配置周边检索功能,将检索类型设置为"美食":
- (void)searchCurrentLocationWithKeyword:(NSString *)keyword { CLLocationCoordinate2D centerCoord = self.mapView.centerCoordinate; QMSPoiSearchOption *option = [[QMSPoiSearchOption alloc] init]; if (keyword.length > 0) { option.keyword = keyword; } option.boundary = [NSString stringWithFormat:@"nearby(%f,%f,2000,1)", centerCoord.latitude, centerCoord.longitude]; [option setFilter:@"category=美食"]; [self.mapSearcher searchWithPoiSearchOption:option]; }
3、解析检索结果,移动地图视野,并将结果显示在tableView上:
- (void)searchWithPoiSearchOption:(QMSPoiSearchOption *)poiSearchOption didReceiveResult:(QMSPoiSearchResult *)poiSearchResult { NSLog(@"%@", poiSearchResult); if (poiSearchResult.count == 0) { return; } // 地图移动到搜索结果的第一个位置 if (_searchBar.text.length > 0) { _selectedIndex = 0; QMSPoiData *firstData = poiSearchResult.dataArray[0]; _annotation.coordinate = firstData.location; [self.mapView setCenterCoordinate:firstData.location animated:YES]; } else { _selectedIndex = -1; } _searchResultArray = poiSearchResult.dataArray; [_searchResultTableView reloadData]; }
以上就是核心代码,在Demo中还添加了用于显示地址的TableView以及搜索位置的SearchBar,有兴趣的同学可以在文章最下方进入码云下载完整示例。
示例:搜索西二旗地铁附近的美食
链接
感兴趣的同学可以在码云中下载Demo尝试一下。
-
百度地图开发的笔记(篇2)高仿微信发送位置功能
2018-06-27 16:53:29主要功能(参照微信发送定位): 1.定位所在位置并且展示周边POI(建筑物等信息); 2.移动中央覆盖物,返回其位置周边的POI信息; 3.支持关键词等搜索,每次搜索完成,中央覆盖物移动到第一条POI信息的相应位置;...本篇主要记录在实现这个功能时,遇到的一些问题以及解决,具体的实现代码在下篇文章中贴出
首先看下效果图:
主要功能(参照微信发送定位):
- 1.定位所在位置并且展示周边POI(建筑物等信息);
- 2.拖拽地图完成,返回中心覆盖物所处位置周边的POI信息;
- 3.支持关键词等搜索,每次搜索完成,中央覆盖物移动到第一条POI信息的相应位置;
- 4.点击右上角的图标,中央覆盖物回到所定位的位置;
- 5.点击下边列表的某条数据,将中央覆盖物移至该条数据对应的位置;
- 6.发送定位时,有相应的地图位置截图和地址信息.
主要问题及解决
1.如何添加地图中央覆盖物,随着对地图的拖拽,覆盖物始终在地图中心?
第一眼是不是感觉中央覆盖物,不就是添加个marker,一开始我也这么实现的,然后监听地图的移动,不断让marker移动到屏幕的地图中心点。
虽然也是能实现,但是明显界面卡顿,核心代码在下图:这种方法很明显,是不行的。后来参照58速运App定位功能,对其布局进行查看,原来中央覆盖物是一个ImageView,浮动在MapView中央。那就可以这么实现了。用一个相对布局,里面放MapView和ImageView,ImageView处于MapView的中央位置,就这么搞定咯。
2.当用户拖拽地图时,如何监听地图的移动?
这个问题看着很简单,但我却觉得如果api选择错了,那就头痛了。
刚开始我用OnMapStatusChangeListener类来实现监听地图的移动,因为该类可以知道 "地图状态的改变原因、状态改变的过程(开始改变/正在改变/改变结束),使用这个类的话,要注意判断地图状态的改变原因,因为MapStatusUpdate相关类也是会触发该类。
由于OnMapStatusChangeListener类并不好控制,后面用OnMapTouchListener类将其替换,明显少了很多处理逻辑.
3.当地图被拖动时,如何获取中央覆盖物的地理坐标?
中央覆盖物是由于相对布局才处于MapView的中央,跟MapView只是层叠的关系,百度地图api中有个Projection类,用于屏幕像素点坐标系统和地球表面经纬度点坐标系统之间的变换,那我就尝试着获取ImageView的坐标,通过Projection类将屏幕坐标转换成地理坐标,刚开始试了确实可行;
后面发现地理坐标偏差较大,源于后面要通过中央覆盖物的地理坐标,获取到周边的数据,发现数据有问题,获取到的数据都不是中央覆盖物周边的。
后来在百度api文档中,翻到MapStatus这个类,这个类主要记录地图的状态,可以获取到地图操作的中心点、地图操作中心点在屏幕中的坐标等。由于覆盖物处于地图的中央,那么通过MapStatus获取到的中心地理坐标值,该值也就是该中心覆盖物的坐标。
4.如何通过中央覆盖物的地理坐标,获取到周边的POI数据?
刚开始是用周边检索功能来获取周边的POI数据,但周边检索功能必须设置keyword,那根据微信的功能实现,我并不能对keyword赋值,比如赋值 “大厦”,那获取到的数据都是关于周边大厦的。后来尝试着不用keyword来获取,但由于keyword的限制,也难以像微信一样。
后面在百度文档中找到GeoCoder这个类,可以通过地理坐标反地理编码,从而获取到周边的POI数据。
5.点击下边列表的某条数据,如何将中央覆盖物移至该数据对应的位置?
由于获取到的数据是带有地址信息和地理坐标的,可以通过MapStatusUpdate/MapStatusUpdateFactory,移动地图。这样就以中央覆盖物为参照物,而地图进行移动, 眼睛却察觉到是中央覆盖物移至该数据对应的位置.
6.发送定位时,对mapView进行截图,图中没有中央覆盖物?
使用百度api中的SnapshotReadyCallback类对mapView进行截图,所截取到的图中并没有中央覆盖物。这是由于中央覆盖物并不处于mapView这个控件中.
那么利用Android中View的截图方式,在mapView和中央覆盖物ImageView的父布局RelativeLayout外嵌套一层FrameLayout,对FrameLayout这个View进行截图呢?尝试了下,发现所截取的mapView是黑屏的,这就蓝瘦香菇了.
没办法,那就只能狸猫换太子咯。在点击发送定位时,将中央覆盖物隐藏,往地图中央添加marker覆盖物,然后再调用百度api进行截图.
其它
1.上面说的OnMapStatusChangeListener类并不好控制,其中1点看下面截图:
明明是手指触摸,在触发事件中,监听到的地图状态原因是开发者调用,这明显不对。写这篇文章时再测了下,并没再发现监听状态错误的问题,猜测可能是由于MapStatusUpdate等类引起的,具体的就不去深究咯.
2.获取ImageView的坐标,通过Projection类将屏幕坐标转换成地理坐标,偏差很大.下面截图中,地图中心点和中心覆盖物关于屏幕坐标、地理坐标的比较,这可能是因为地图并不是完全显示在手机屏幕的原因,导致偏差问题.
3.百度地图上面的签名跟apk的签名不一致,即sha1值错误
galaxy lib host missing meta-data,make sure you know the right way to integrate galaxy
链接
百度地图开发基础篇
百度地图开发的笔记(篇3)高仿微信发送位置功能GitHub链接
-
利用百度地图Android sdk高仿微信发送位置功能及遇到的问题
2020-08-28 09:57:35给大家介绍了利用百度地图Android sdk高仿微信发送位置功能,在实现此功能的时候遇到点小问题,下面小编给大家列出来,需要的朋友参考下吧 -
Android 腾讯地图 选点定位,仿微信发送位置
2019-03-29 15:10:27效果图: 不需要集成定位、地图,然后标记 回调等繁琐的操作,你只需要一个webview,使用腾讯地图...通过页面跳转的方式调用该组件的时候,开发者需要设置backurl参数,用户点击选中的位置点后,页面跳转至开发者... -
安卓微信相关相关-Android高仿微信发送位置.rar
2019-07-30 09:56:06Android高仿微信发送位置.rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。 -
利用百度地图Android sdk高仿微信发送位置功能
2018-11-09 08:33:16利用百度地图Android sdk高仿微信发送位置功能 [注意:本资源来自网络,如有侵权,请联系我删除,谢谢。] -
仿微信发送位置(高德地图定位)
2019-07-11 11:33:27仿微信发送位置,可以定位以及附近周边位置,搜索功能,获取位置以及经纬度 **源码链接:**https://download.csdn.net/download/jiaosheng1/11328362 -
Android仿微信发送语音消息的功能及示例代码
2020-08-29 14:39:17主要介绍了Android仿微信发送语音消息的功能及示例代码,需要的朋友参考下吧 -
Android仿微信发送语音与播放语音
2018-09-30 17:09:021、这个Demo主要是实现仿微信的发送语音以及播放语音的功能效果。 2、相应的博文地址:https://blog.csdn.net/lpCrazyBoy/article/details/82910825 -
安卓微信相关相关-(无法运行)仿微信发送位置地图选点(百度地图).rar
2019-07-30 09:56:30(无法运行)仿微信发送位置、地图选点(百度地图).rar,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。 -
Android仿微信发送位置-百度地图 模仿微信定位 - 下载 - 搜珍网
2021-06-02 17:20:22压缩包 : cf75407614893f5bafffe5dea3462dea.zip 列表BaiduWeChatPosition/BaiduWeChatPosition/.idea/BaiduWeChatPosition/.idea/workspace.xmlBaiduWeChatPosition/BaiduWeChatPosition/BaiduWeChatPosition/... -
web仿微信发朋友圈选择位置.
2018-02-06 17:54:33web仿微信发朋友圈选择位置.web仿微信发朋友圈选择位置.web仿微信发朋友圈选择位置.