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


      这两天一直捣鼓着地图的选址功能,需要达到的要求是: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

      上面获取到的信息是一个位置的具体信息,如果你想获取就近的POI信息 ,可以在地图结束拖动的代理做如下操作:  

    /**
     滑动地图结束 修改当前位置
     */
    - (void)mapView:(MAMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
    //    self.regeo.location = [AMapGeoPoint locationWithLatitude:mapView.centerCoordinate.latitude longitude:mapView.centerCoordinate.longitude];
        AMapPOIAroundSearchRequest *r = [[AMapPOIAroundSearchRequest alloc] init];
        r.location = [AMapGeoPoint locationWithLatitude:mapView.centerCoordinate.latitude longitude:mapView.centerCoordinate.longitude];
        r.radius = 500; //查找半径 单位:米
        r.sortrule = 0; // 排序: 0距离  1综合
    //    r.types = @"写字楼|公寓|建筑|餐饮"; //搜索的类型 多个用'|'分割
        [self.search AMapPOIAroundSearch:r];
    //    [self.search AMapReGoecodeSearch:self.regeo];
        
        if (self.annotationView) {
            
            [UIView animateWithDuration:0.15 animations:^{
                self.annotationView.centerOffset = CGPointMake(0, -18 + offsetY);
            }];
        }
    }

    然后在poi查找结果回调中获得数据:

    /**
     * @brief POI查询回调函数
     * @param request  发起的请求,具体字段参考 AMapPOISearchBaseRequest 及其子类。
     * @param response 响应结果,具体字段参考 AMapPOISearchResponse 。
     */
    - (void)onPOISearchDone:(AMapPOISearchBaseRequest *)request response:(AMapPOISearchResponse *)response{
    
    
        for (AMapAOI *poi in response.pois) {
            NSLog(@"%@",poi.name);
        }
    
    }

    提醒我自己:  1, 添加搜索栏的时候如果直接用Masonry添加约束, 刚进控制器那会儿还正常,  但是一点击搜索, 搜索栏就会跑到屏幕外(左上角屏幕之外)。解决办法是添加一个父控件,然后再将搜索栏用frame的形式添加到父控件。2,创建后的选取位置的大头针视图(是视图不是模型)  用属性保存起来 在地图即将拖动和拖动完成后的代理通过改变 centerOffset 来让大头针有动画效果(当然,也有其他方法可实现) 3,

  • 相关阅读:
    css3 animate 和关键帧 @-webkit-keyframes
    CSS3 线性渐变(linear-gradient)
    css3 transition平滑过渡
    css3 变形设计涂鸦墙
    css3 图片翻转效果
    溢出隐藏
    顺序表的实现
    数论学习
    从BF算法到kmp算法详解
    王红梅、胡明、王涛编著的《数据结构c++》(第二版)模板类链表超详细代码
  • 原文地址:https://www.cnblogs.com/yulongjiayuan/p/7406741.html
Copyright © 2020-2023  润新知