利用高德地圖完成用戶地圖選址,包括搜索位置和標籤固定居中

  這兩天一直搗鼓着地圖的選址功能,須要達到的要求是:1,能用戶定位  2,大頭針固定在地圖中心,拖動地圖中止後獲取到該大頭針的位置信息    3,能經過搜索框搜索到咱們輸入的地址git

   主要思路:大頭針分爲兩個   一個是用戶的位置大頭針  另外一個是所選取的位置的大頭針(包括拖動後的大頭針和搜索功能查找到位置的大頭針,公用一個大頭針  )而且兩個大頭針都成爲控制器器屬性。數組

  我使用到的高德地圖sdk是:app

    'AMap3DMap' , '5.2.1' #高德3D地圖ide

    'AMapSearch' , '5.2.1' #高德搜索功能函數

    'AMapLocation', '2.4.0'  #定位動畫

完整代碼以下:ui

#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查找結果回調中得到數據:atom

/**
 * @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,spa

相關文章
相關標籤/搜索