利用高德地图完成用户地图选址,包括搜索位置和标签固定居中

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,

 

以上是关于利用高德地图完成用户地图选址,包括搜索位置和标签固定居中的主要内容,如果未能解决你的问题,请参考以下文章

前端通过高德地图实现 定位,拖拽选址,搜索选址,搜索记录,城市切换推荐

高德地图的位置搜索

高德地图怎样实现实时定位,得到当前地点的坐标,位置

高德地图怎样自已规划驾车线路?

启动高德地图后如何自动定位我的位置

通过IP地址获取所在城市(高德)