利用高德地图完成用户地图选址,包括搜索位置和标签固定居中
Posted 御龙家园
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用高德地图完成用户地图选址,包括搜索位置和标签固定居中相关的知识,希望对你有一定的参考价值。
这两天一直捣鼓着地图的选址功能,需要达到的要求是:1,能用户定位 2,大头针固定在地图中心,拖动地图停止后获取到该大头针的位置信息 3,能通过搜索框搜索到我们输入的地址
主要思路:大头针分为两个 一个是用户的位置大头针 另一个是所选取的位置的大头针(包括拖动后的大头针和搜索功能查找到位置的大头针,公用一个大头针 )并且两个大头针都成为控制器器属性。
我使用到的高德地图sdk是:
‘AMap3DMap‘ , ‘5.2.1‘ #高德3D地图
‘AMapSearch‘ , ‘5.2.1‘ #高德搜索功能
‘AMapLocation‘, ‘2.4.0‘ #定位
完整代码如下:
#define Screen_Width [UIScreen mainScreen].bounds.size.width #define Screen_Height [UIScreen mainScreen].bounds.size.height @interface MapAddressViewController ()<MAMapViewDelegate, AMapSearchDelegate, UISearchBarDelegate, UISearchResultsUpdating, UITableViewDataSource, UITableViewDelegate, AMapLocationManagerDelegate> ///定位 @property (nonatomic, strong) AMapLocationManager *locationManager; ///定位按钮 @property(nonatomic,weak) UIButton *locationBtn; ///搜索 控制器 @property (nonatomic, strong) UISearchController *searchController; ///展示搜索结果tableView @property (nonatomic, strong) UITableView *tableView; ///搜索提示 模型 @property (nonatomic, strong) NSMutableArray *tips; ///地图 @property (nonatomic, strong) MAMapView *mapView; ///大头针 @property (nonatomic, strong) MAPointAnnotation *pointAnnotation; ///大头针view视图 @property(nonatomic, strong) MAAnnotationView *annotationView; ///逆地理编码 @property (nonatomic, strong) AMapReGeocodeSearchRequest *regeo; ///逆地理编码使用的 @property (nonatomic, strong) AMapSearchAPI *search; ///单次定位的回调 @property (nonatomic, copy) AMapLocatingCompletionBlock completionBlock; //显示地址的label @property(nonatomic, weak) UILabel *addressL; @end @implementation MapAddressViewController #pragma mark - 懒加载 - (AMapLocationManager *)locationManager { if (!_locationManager) { _locationManager = [[AMapLocationManager alloc]init]; [_locationManager setDesiredAccuracy:kCLLocationAccuracyHundredMeters]; _locationManager.locationTimeout = 2; _locationManager.reGeocodeTimeout = 2; } return _locationManager; } - (AMapReGeocodeSearchRequest *)regeo { if (!_regeo) { _regeo = [[AMapReGeocodeSearchRequest alloc]init]; _regeo.requireExtension = YES; } return _regeo; } - (MAPointAnnotation *)pointAnnotation { if (!_pointAnnotation) { _pointAnnotation = [[MAPointAnnotation alloc]init]; } return _pointAnnotation; } - (AMapSearchAPI *)search { if (!_search) { _search = [[AMapSearchAPI alloc]init]; _search.delegate = self; } return _search; } #pragma mark - View周期 - (void)viewDidLoad { [super viewDidLoad]; self.navigationController.navigationBar.translucent = true;// ssslll //初始化地图UI [self setUpMap]; //初始化附加UI [self setUpUI]; //初始化tableView [self initTableView]; } - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated]; self.searchController.active = NO; } #pragma mark - 初始化 / 方法调用 /** 添加地图背景 */ - (void)setUpMap{ //在viewDidLoad里面添加背景和定位功能 //地图 self.mapView = [[MAMapView alloc]initWithFrame:CGRectMake(0, 0, Screen_Width, Screen_Height)]; [self.view addSubview:self.mapView]; self.mapView.showsUserLocation = YES; self.mapView.delegate = self; self.mapView.userTrackingMode = MAUserTrackingModeFollow; self.mapView.showsScale = NO; //用户定位的点设置 MAUserLocationRepresentation *r = [[MAUserLocationRepresentation alloc] init]; r.showsAccuracyRing = NO;///精度圈是否显示,默认YES // r.locationDotFillColor = [UIColor grayColor];///定位点蓝色圆点颜色,不设置默认蓝色 r.showsHeadingIndicator = YES;///是否显示方向指示(MAUserTrackingModeFollowWithHeading模式开启)。默认为YES [self.mapView updateUserLocationRepresentation:r]; //初始化单次定位的回调 (要在定位之前先初始化) [self initCompleteBlock]; //定位 [self.locationManager requestLocationWithReGeocode:YES completionBlock:self.completionBlock]; } - (void)setUpUI{ /******************* 搜索框 ***********************/ UIView *searchV = [[UIView alloc] init]; searchV.backgroundColor = [UIColor whiteColor]; [self.view addSubview:searchV]; [searchV mas_makeConstraints:^(MASConstraintMaker *make) { make.height.offset(40); make.left.right.offset(0); make.top.offset(64); }]; [searchV layoutIfNeeded]; self.tips = [NSMutableArray array];//poi搜索提示模型数组 self.searchController = [[UISearchController alloc] initWithSearchResultsController:nil]; self.searchController.searchResultsUpdater = self; self.searchController.dimsBackgroundDuringPresentation = NO; self.searchController.hidesNavigationBarDuringPresentation = NO; self.searchController.searchBar.delegate = self; self.searchController.searchBar.placeholder = @"请输入关键字"; [self.searchController.searchBar sizeToFit]; [searchV addSubview:self.searchController.searchBar]; self.searchController.searchBar.frame = searchV.bounds; /******************* 定位点 ***********************/ UIButton *locationBtn = [[UIButton alloc] init]; self.locationBtn = locationBtn; { [locationBtn setImage:[UIImage imageNamed:@"locationBtn_n"] forState:UIControlStateNormal]; [locationBtn setImage:[UIImage imageNamed:@"locationBtn_h"] forState:UIControlStateHighlighted]; [self.view addSubview:locationBtn]; CGFloat space_bottom = 30; CGFloat space_left = 0; CGFloat locationBtnWH = 50; [locationBtn mas_makeConstraints:^(MASConstraintMaker *make) { make.bottom.equalTo(self.view).offset(-(49 + space_bottom)); make.left.equalTo(self.view).offset(space_left); make.width.height.equalTo(@(locationBtnWH)); }]; [locationBtn addTarget:self action:@selector(currentLoacation:) forControlEvents:UIControlEventTouchUpInside]; } /******************* 地址显示 ***********************/ UIView *addressV = [[UIView alloc] init]; addressV.backgroundColor = [UIColor whiteColor]; [self.view addSubview:addressV]; [addressV mas_makeConstraints:^(MASConstraintMaker *make) { make.height.offset(52); make.left.right.offset(0); make.bottom.offset(-10); }]; UILabel *addressL = [[UILabel alloc] init]; [addressV addSubview:addressL]; [addressL mas_makeConstraints:^(MASConstraintMaker *make) { make.right.bottom.top.offset(0); make.left.offset(10); }]; self.addressL = addressL; } /** 初始化定位回调 */ - (void)initCompleteBlock{ __weak MapAddressViewController *weakSelf = self; self.completionBlock = ^(CLLocation *location, AMapLocationReGeocode *regeocode, NSError *error) { if (error) { return ; } weakSelf.pointAnnotation.coordinate = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude); if (weakSelf.mapView.annotations.count < 2) { [weakSelf.mapView addAnnotation:weakSelf.pointAnnotation]; } [weakSelf.mapView setCenterCoordinate:CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude) animated:YES]; //让地图在缩放过程中移到当前位置试图 [weakSelf.mapView setZoomLevel:15.1 animated:YES]; // MapAddressViewController *strongSelf = weakSelf; // [strongSelf addAnnotationToMapView:weakSelf.pointAnnotation]; NSLog(@"%ld",weakSelf.mapView.annotations.count); }; } - (void)initTableView { // CGFloat tableY = CGRectGetMaxY(self.navigationController.navigationBar.frame); self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 44+44+20, self.view.frame.size.width, self.view.frame.size.height - 100) style:UITableViewStylePlain]; self.tableView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.tableView.delegate = self; self.tableView.dataSource = self; self.tableView.hidden = YES; [self.view addSubview:self.tableView]; } /* 输入提示 搜索.*/ - (void)searchTipsWithKey:(NSString *)key { if (key.length == 0) { return; } AMapInputTipsSearchRequest *tips = [[AMapInputTipsSearchRequest alloc] init]; tips.keywords = key; tips.city = @"厦门"; // tips.cityLimit = YES; 是否限制城市 [self.search AMapInputTipsSearch:tips]; } - (void)clearAndShowAnnotationWithTip:(AMapTip *)tip { /* 清除annotations & overlays */ // [self clear]; // ---k if (tip.uid != nil && tip.location != nil) /* 可以直接在地图打点 */ { CLLocationCoordinate2D location = CLLocationCoordinate2DMake(tip.location.latitude, tip.location.longitude); [self.mapView setCenterCoordinate:location]; } else if(tip.uid == nil && tip.location == nil)/* 品牌名,进行POI关键字搜索 */ { AMapPOIKeywordsSearchRequest *request = [[AMapPOIKeywordsSearchRequest alloc] init]; request.keywords = tip.name; request.city = @"厦门"; request.requireExtension = YES; [self.search AMapPOIKeywordsSearch:request]; } } #pragma mark - 点击事件 /** 点击回到 用户当前位置 */ - (void)currentLoacation:(UIButton *)btn{ //定位 [self.locationManager requestLocationWithReGeocode:YES completionBlock:self.completionBlock]; } #pragma mark - MAMapViewDelegate /** * @brief 根据anntation生成对应的View 自定义大头针代理 * @param mapView 地图View * @param annotation 指定的标注 * @return 生成的标注View */ - (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id<MAAnnotation>)annotation { //用户位置的大头针 if ([annotation isKindOfClass:[MAUserLocation class]]) { return nil; } //选取定位的大头针 if ([annotation isKindOfClass:[MAPointAnnotation class]]) { static NSString *reuseIdetifier = @"annotationReuseIndetifier"; MAAnnotationView *annotationView = (MAAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:reuseIdetifier]; if (annotationView == nil) { annotationView = [[MAAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:reuseIdetifier]; } //放一张大头针图片即可 annotationView.image = [UIImage imageNamed:@"personal_locate"]; annotationView.centerOffset = CGPointMake(0, -18); self.annotationView = annotationView ; // ---k return annotationView; } return nil; } /** * @brief 地图将要发生移动时调用此接口 * @param mapView 地图view * @param wasUserAction 标识是否是用户动作 */ - (void)mapView:(MAMapView *)mapView mapWillMoveByUser:(BOOL)wasUserAction{ if (self.annotationView) { [UIView animateWithDuration:0.15 animations:^{ self.annotationView.centerOffset = CGPointMake(0, -18 - 5); }]; } } /** 滑动地图过程 代理 */ - (void)mapViewRegionChanged:(MAMapView *)mapView { self.pointAnnotation.coordinate = mapView.centerCoordinate; } /** 滑动地图结束 修改当前位置 */ - (void)mapView:(MAMapView *)mapView regionDidChangeAnimated:(BOOL)animated { self.regeo.location = [AMapGeoPoint locationWithLatitude:mapView.centerCoordinate.latitude longitude:mapView.centerCoordinate.longitude]; [self.search AMapReGoecodeSearch:self.regeo]; if (self.annotationView) { [UIView animateWithDuration:0.15 animations:^{ self.annotationView.centerOffset = CGPointMake(0, -18 + 5); }]; }} /** 滑动结束调用search的代理进行逆地理编码得到地理位置 */ - (void)onReGeocodeSearchDone:(AMapReGeocodeSearchRequest *)request response:(AMapReGeocodeSearchResponse *)response { if (response.regeocode != nil) { AMapReGeocode *reocode = response.regeocode; //地图标注的点的位置信息全在reoceode里面了 NSLog(@"%@",reocode.formattedAddress); AMapAddressComponent *address = reocode.addressComponent;//地址组成要素 AMapStreetNumber *streeNumber = address.streetNumber;//门牌信息 NSLog(@"%@---%@---%@---%@---(%@)",address.district,address.township,streeNumber.street,streeNumber.number,address.building); self.addressL.text = [NSString stringWithFormat:@"%@%@%@%@",address.district,address.township,streeNumber.street,streeNumber.number]; } } #pragma mark - AMapSearchDelegate /** * @brief 输入提示查询回调函数 * @param request 发起的请求,具体字段参考 AMapInputTipsSearchRequest 。 * @param response 响应结果,具体字段参考 AMapInputTipsSearchResponse 。 */ - (void)onInputTipsSearchDone:(AMapInputTipsSearchRequest *)request response:(AMapInputTipsSearchResponse *)response { if (response.count == 0) { return; } [self.tips setArray:response.tips]; // for (AMapTip in <#collection#>) { // <#statements#> // } [self.tableView reloadData]; } #pragma mark - UISearchResultsUpdating - (void)updateSearchResultsForSearchController:(UISearchController *)searchController { self.tableView.hidden = !searchController.isActive; [self searchTipsWithKey:searchController.searchBar.text]; if (searchController.isActive && searchController.searchBar.text.length > 0) { searchController.searchBar.placeholder = searchController.searchBar.text; } } #pragma mark - UITableViewDataSource - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.tips.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *tipCellIdentifier = @"tipCellIdentifier"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:tipCellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:tipCellIdentifier]; cell.imageView.image = [UIImage imageNamed:@"locate"]; } AMapTip *tip = self.tips[indexPath.row]; if (tip.location == nil) { cell.imageView.image = [UIImage imageNamed:@"search"]; } cell.textLabel.text = tip.name; cell.detailTextLabel.text = tip.address; return cell; } #pragma mark - UITableViewDelegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { AMapTip *tip = self.tips[indexPath.row]; NSLog(@"%@--%@---%@--- ",tip.name,tip.district,tip.address); [self clearAndShowAnnotationWithTip:tip]; self.searchController.active = NO; } @end
提醒我自己: 1, 添加搜索栏的时候如果直接用Masonry添加约束, 刚进控制器那会儿还正常, 但是一点击搜索, 搜索栏就会跑到屏幕外(左上角屏幕之外)。解决办法是添加一个父控件,然后再将搜索栏用frame的形式添加到父控件。2,创建后的选取位置的大头针视图(是视图不是模型) 用属性保存起来 在地图即将拖动和拖动完成后的代理通过改变 centerOffset 来让大头针有动画效果(当然,也有其他方法可实现) 3,
以上是关于利用高德地图完成用户地图选址,包括搜索位置和标签固定居中的主要内容,如果未能解决你的问题,请参考以下文章