其它技术点开发技巧iOS

【iOS】高德地图MAMapKit的使用:导航功能。

2017-03-10  本文已影响2945人  attackGiant

http://www.jianshu.com/p/73a6acba45aa 之后的导航功能。

93039.png

线路规划主要代码:

 //进行路径规划
    [self.driveManager calculateDriveRouteWithStartPoints:@[self.startPoint]
                                                endPoints:@[self.endPoint]
                                                wayPoints:nil
                                          drivingStrategy:AMapNaviDrivingStrategySingleDefault];

接下来叙述项目配置:
1、去高德开放平台下载对应的导航AMapNaviKit.framework并解压

21112.png

2、将AMapNaviKit.framework拖入工程,记得选择:

121212.png

3、添加导航需要的资源文件 AMapNavi.bundle,如图:

223.png 323.png

4、下面开始代码部分:(自定义控制器,将下面的代码复制进控制器即可,只需要在上个控制器设置好CLLocationCoordinate2D coor、MAUserLocation *currentUL即可进行导航功能)
在导航控制器.h文件导入头文件#import <AMapNaviKit/AMapNaviKit.h>并添加几个属性:

@property (nonatomic, strong) AMapNaviDriveManager *driveManager;

@property (nonatomic, strong) AMapNaviDriveView *driveView;

@property (nonatomic, strong) MAUserLocation *currentUL;//导航起始位置,即用户当前的位置

@property (nonatomic, assign) CLLocationCoordinate2D coor;//导航终点位置

导航控制器.m文件:


#import "SpeechSynthesizer.h"
#import "MoreMenuView.h"

@interface GPSNaviViewController ()<AMapNaviDriveManagerDelegate, AMapNaviDriveViewDelegate, MoreMenuViewDelegate>

@property (nonatomic, strong) AMapNaviPoint *startPoint;
@property (nonatomic, strong) AMapNaviPoint *endPoint;

@property (nonatomic, strong) MoreMenuView *moreMenu;

@end

@implementation GPSNaviViewController

#pragma mark - Life Cycle

- (void)viewDidLoad
{
    [super viewDidLoad];
    
//    [self setNavigationBackItem];
    
    [self initProperties];
    
    [self initDriveView];
    
    [self initDriveManager];
    
    [self initMoreMenu];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    
    self.navigationController.navigationBarHidden = YES;
    self.navigationController.toolbarHidden = YES;
}

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    
    [self calculateRoute];
}

- (void)viewWillLayoutSubviews
{
    UIInterfaceOrientation interfaceOrientation = [[UIApplication sharedApplication] statusBarOrientation];
    if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0)
    {
        interfaceOrientation = self.interfaceOrientation;
    }
    
    if (UIInterfaceOrientationIsPortrait(interfaceOrientation))
    {
        [self.driveView setIsLandscape:NO];
    }
    else if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
    {
        [self.driveView setIsLandscape:YES];
    }
}

- (BOOL)prefersStatusBarHidden
{
    return YES;
}

#pragma mark - Initalization

- (void)initProperties
{
    //设置导航的起点和终点
    self.startPoint = [AMapNaviPoint locationWithLatitude:_currentUL.coordinate.latitude longitude:_currentUL.coordinate.longitude];
    self.endPoint   = [AMapNaviPoint locationWithLatitude:_coor.latitude longitude:_coor.longitude];
}

- (void)initDriveManager
{
    if (self.driveManager == nil)
    {
        self.driveManager = [[AMapNaviDriveManager alloc] init];
        [self.driveManager setDelegate:self];
        
        [self.driveManager setAllowsBackgroundLocationUpdates:YES];
        [self.driveManager setPausesLocationUpdatesAutomatically:NO];
        
        //将driveView添加为导航数据的Representative,使其可以接收到导航诱导数据
        [self.driveManager addDataRepresentative:self.driveView];
    }
}

- (void)initDriveView
{
    if (self.driveView == nil)
    {
        self.driveView = [[AMapNaviDriveView alloc] initWithFrame:CGRectMake(0, 0, KScreenWidth, KScreenHeight)];
        self.driveView.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
        [self.driveView setDelegate:self];
        
        [self.view addSubview:self.driveView];
    }
}

- (void)initMoreMenu
{
    if (self.moreMenu == nil)
    {
        self.moreMenu = [[MoreMenuView alloc] init];
        self.moreMenu.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight;
        
        [self.moreMenu setDelegate:self];
    }
}

#pragma mark - Route Plan

- (void)calculateRoute
{
    //进行路径规划
    [self.driveManager calculateDriveRouteWithStartPoints:@[self.startPoint]
                                                endPoints:@[self.endPoint]
                                                wayPoints:nil
                                          drivingStrategy:AMapNaviDrivingStrategySingleDefault];
}

#pragma mark - AMapNaviDriveManager Delegate

- (void)driveManager:(AMapNaviDriveManager *)driveManager error:(NSError *)error
{
    NSLog(@"error:{%ld - %@}", (long)error.code, error.localizedDescription);
}

- (void)driveManagerOnCalculateRouteSuccess:(AMapNaviDriveManager *)driveManager
{
    NSLog(@"onCalculateRouteSuccess");
    
    //算路成功后开始GPS导航
    [self.driveManager startGPSNavi];
}

- (void)driveManager:(AMapNaviDriveManager *)driveManager onCalculateRouteFailure:(NSError *)error
{
    NSLog(@"onCalculateRouteFailure:{%ld - %@}", (long)error.code, error.localizedDescription);
}

- (void)driveManager:(AMapNaviDriveManager *)driveManager didStartNavi:(AMapNaviMode)naviMode
{
    NSLog(@"didStartNavi");
}

- (void)driveManagerNeedRecalculateRouteForYaw:(AMapNaviDriveManager *)driveManager
{
    NSLog(@"needRecalculateRouteForYaw");
}

- (void)driveManagerNeedRecalculateRouteForTrafficJam:(AMapNaviDriveManager *)driveManager
{
    NSLog(@"needRecalculateRouteForTrafficJam");
}

- (void)driveManager:(AMapNaviDriveManager *)driveManager onArrivedWayPoint:(int)wayPointIndex
{
    NSLog(@"onArrivedWayPoint:%d", wayPointIndex);
}

- (void)driveManager:(AMapNaviDriveManager *)driveManager playNaviSoundString:(NSString *)soundString soundStringType:(AMapNaviSoundType)soundStringType
{
    NSLog(@"playNaviSoundString:{%ld:%@}", (long)soundStringType, soundString);
    
    [[SpeechSynthesizer sharedSpeechSynthesizer] speakString:soundString];
}

- (void)driveManagerDidEndEmulatorNavi:(AMapNaviDriveManager *)driveManager
{
    NSLog(@"didEndEmulatorNavi");
}

- (void)driveManagerOnArrivedDestination:(AMapNaviDriveManager *)driveManager
{
    NSLog(@"onArrivedDestination");
}

#pragma mark - AMapNaviWalkViewDelegate

- (void)driveViewCloseButtonClicked:(AMapNaviDriveView *)driveView
{
    //停止导航
    [self.driveManager stopNavi];
    [self.driveManager removeDataRepresentative:self.driveView];
             
    //停止语音
    [[SpeechSynthesizer sharedSpeechSynthesizer] stopSpeak];
    
    [self.navigationController popViewControllerAnimated:YES];
}

- (void)driveViewMoreButtonClicked:(AMapNaviDriveView *)driveView
{
    //配置MoreMenu状态
    [self.moreMenu setTrackingMode:self.driveView.trackingMode];
    [self.moreMenu setShowNightType:self.driveView.showStandardNightType];
    
    [self.moreMenu setFrame:self.view.bounds];
    [self.view addSubview:self.moreMenu];
}

- (void)driveViewTrunIndicatorViewTapped:(AMapNaviDriveView *)driveView
{
    NSLog(@"TrunIndicatorViewTapped");
}

- (void)driveView:(AMapNaviDriveView *)driveView didChangeShowMode:(AMapNaviDriveViewShowMode)showMode
{
    NSLog(@"didChangeShowMode:%ld", (long)showMode);
}

#pragma mark - MoreMenu Delegate

- (void)moreMenuViewFinishButtonClicked
{
    [self.moreMenu removeFromSuperview];
}

- (void)moreMenuViewNightTypeChangeTo:(BOOL)isShowNightType
{
    [self.driveView setShowStandardNightType:isShowNightType];
}

- (void)moreMenuViewTrackingModeChangeTo:(AMapNaviViewTrackingMode)trackingMode
{
    [self.driveView setTrackingMode:trackingMode];
}

在导航控制器.m文件中引用的#import "SpeechSynthesizer.h" 为导航时的语音功能、

import "MoreMenuView.h"为偏好设置界面

0383.png

SpeechSynthesizer.h文件内容:

#import <AVFoundation/AVFoundation.h>

/**
 *  iOS7及以上版本可以使用 AVSpeechSynthesizer 合成语音
 *
 *  或者采用"科大讯飞"等第三方的语音合成服务
 */
@interface SpeechSynthesizer : NSObject

+ (instancetype)sharedSpeechSynthesizer;

- (void)speakString:(NSString *)string;

- (void)stopSpeak;

SpeechSynthesizer.m文件内容:

@interface SpeechSynthesizer () <AVSpeechSynthesizerDelegate>

@property (nonatomic, strong, readwrite) AVSpeechSynthesizer *speechSynthesizer;

@end

@implementation SpeechSynthesizer

+ (instancetype)sharedSpeechSynthesizer
{
    static id sharedInstance = nil;
    
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[SpeechSynthesizer alloc] init];
    });
    return sharedInstance;
}

- (instancetype)init
{
    if (self = [super init])
    {
        [self buildSpeechSynthesizer];
    }
    return self;
}

- (void)buildSpeechSynthesizer
{
    if ([[[UIDevice currentDevice] systemVersion] floatValue] < 7.0)
    {
        return;
    }
    
    //简单配置一个AVAudioSession以便可以在后台播放声音,更多细节参考AVFoundation官方文档
    AVAudioSession *session = [AVAudioSession sharedInstance];
    [session setCategory:AVAudioSessionCategoryPlayback error:NULL];
    
    self.speechSynthesizer = [[AVSpeechSynthesizer alloc] init];
    [self.speechSynthesizer setDelegate:self];
}

- (void)speakString:(NSString *)string
{
    if (self.speechSynthesizer)
    {
        AVSpeechUtterance *aUtterance = [AVSpeechUtterance speechUtteranceWithString:string];
        [aUtterance setVoice:[AVSpeechSynthesisVoice voiceWithLanguage:@"zh-CN"]];
        
        //iOS语音合成在iOS8及以下版本系统上语速异常
        if ([[[UIDevice currentDevice] systemVersion] floatValue] < 8.0)
        {
            aUtterance.rate = 0.25;//iOS7设置为0.25
        }
        else if ([[[UIDevice currentDevice] systemVersion] floatValue] < 9.0)
        {
            aUtterance.rate = 0.15;//iOS8设置为0.15
        }
        
        if ([self.speechSynthesizer isSpeaking])
        {
            [self.speechSynthesizer stopSpeakingAtBoundary:AVSpeechBoundaryWord];
        }
        
        [self.speechSynthesizer speakUtterance:aUtterance];
    }
}

- (void)stopSpeak
{
    if (self.speechSynthesizer)
    {
        [self.speechSynthesizer stopSpeakingAtBoundary:AVSpeechBoundaryImmediate];
    }
}

MoreMenuView.h文件内容:

#import <AMapNaviKit/AMapNaviCommonObj.h>

@protocol MoreMenuViewDelegate;

@interface MoreMenuView : UIView

@property (nonatomic, assign) id<MoreMenuViewDelegate> delegate;

@property (nonatomic, assign) AMapNaviViewTrackingMode trackingMode;
@property (nonatomic, assign) BOOL showNightType;

@end

@protocol MoreMenuViewDelegate <NSObject>
@optional

- (void)moreMenuViewFinishButtonClicked;
- (void)moreMenuViewTrackingModeChangeTo:(AMapNaviViewTrackingMode)trackingMode;
- (void)moreMenuViewNightTypeChangeTo:(BOOL)isShowNightType;

MoreMenuView.m文件内容:

#define kFinishButtonHeight     40.0f
#define kOptionTableViewHieght  200.0f
#define kTableViewHeaderHeight  30.0f
#define kTableViewCellHeight    50.0f

@interface MoreMenuView ()<UITableViewDataSource, UITableViewDelegate>
{
    UIView *_maskView;
    
    UITableView *_optionTableView;
    NSArray *_sections;
    NSArray *_options;
    
    UISegmentedControl *_viewModeSeg;
    UISegmentedControl *_nightTypeSeg;
    
    UIButton *_finishButton;
}

@end

@implementation MoreMenuView

@synthesize trackingMode = _trackingMode;
@synthesize showNightType = _showNightType;

#pragma mark - Initialization

- (instancetype)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame])
    {
        self.backgroundColor = [UIColor clearColor];
        
        [self initProperties];
        
        [self createMoreMenuView];
    }
    
    return self;
}

- (void)initProperties
{
    _sections = @[@"偏好设置"];
    
    _options = @[@[@"跟随模式", @"昼夜模式"]];
}

- (void)createMoreMenuView
{
    [self initMaskView];
    
    [self initTableView];
    
    [self initFinishButton];
}

- (void)initMaskView
{
    _maskView = [[UIView alloc] initWithFrame:self.bounds];
    _maskView.backgroundColor = [UIColor grayColor];
    _maskView.alpha = 0.5;
    _maskView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    
    [self addSubview:_maskView];
}

- (void)initTableView
{
    _optionTableView = [[UITableView alloc] initWithFrame:CGRectMake(0, CGRectGetHeight(self.bounds) - kFinishButtonHeight - kOptionTableViewHieght, CGRectGetWidth(self.bounds), kOptionTableViewHieght)
                                                    style:UITableViewStylePlain];
    _optionTableView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
    _optionTableView.backgroundColor = [UIColor whiteColor];
    _optionTableView.delegate = self;
    _optionTableView.dataSource = self;
    _optionTableView.allowsSelection = NO;
    
    [self addSubview:_optionTableView];
}

- (void)initFinishButton
{
    _finishButton = [[UIButton alloc] initWithFrame:CGRectMake(0, CGRectGetHeight(self.bounds) - kFinishButtonHeight, CGRectGetWidth(self.bounds), kFinishButtonHeight)];
    _finishButton.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
    [_finishButton setBackgroundColor:[UIColor blueColor]];
    [_finishButton setTitle:@"完 成" forState:UIControlStateNormal];
    [_finishButton addTarget:self action:@selector(finishButtonAction:) forControlEvents:UIControlEventTouchUpInside];
    
    [self addSubview:_finishButton];
}

#pragma mark - TableView Delegate

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return kTableViewHeaderHeight;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return kTableViewCellHeight;
}

#pragma mark - TableView DataSource Delegate

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return _sections.count;
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    return _sections[section];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [_options[section] count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *optionName = _options[indexPath.section][indexPath.row];
    
    if ([optionName isEqualToString:@"跟随模式"])
    {
        return [self tableViewCellForViewMode];
    }
    else if ([optionName isEqualToString:@"昼夜模式"])
    {
        return [self tableViewCellForNightType];
    }
    
    return nil;
}

#pragma mark - Custom TableView Cell

- (UITableViewCell *)tableViewCellForViewMode
{
    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"ViewModeCellIdentifier"];
    
    _viewModeSeg = [[UISegmentedControl alloc] initWithItems:@[@"正北朝上" , @"车头朝上"]];
    [_viewModeSeg setFrame:CGRectMake(160, (kTableViewCellHeight - 30)/2.0, 150, 30)];
    _viewModeSeg.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
    [_viewModeSeg setTitleTextAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14]} forState:UIControlStateNormal];
    [_viewModeSeg addTarget:self action:@selector(viewModeSegmentedControlAction:) forControlEvents:UIControlEventValueChanged];
    
    UILabel *optionNameLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 0, 120, kTableViewCellHeight)];
    optionNameLabel.textAlignment = NSTextAlignmentLeft;
    optionNameLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
    optionNameLabel.font = [UIFont systemFontOfSize:18];
    optionNameLabel.text = @"跟随模式:";
    
    if (self.trackingMode == AMapNaviViewTrackingModeMapNorth)
    {
        [_viewModeSeg setSelectedSegmentIndex:0];
    }
    else if (self.trackingMode == AMapNaviViewTrackingModeCarNorth)
    {
        [_viewModeSeg setSelectedSegmentIndex:1];
    }
    
    [cell.contentView addSubview:optionNameLabel];
    [cell.contentView addSubview:_viewModeSeg];
    
    return cell;
}

- (UITableViewCell *)tableViewCellForNightType
{
    UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"ViewModeCellIdentifier"];
    
    UILabel *optionNameLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 0, 120, kTableViewCellHeight)];
    optionNameLabel.textAlignment = NSTextAlignmentLeft;
    optionNameLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
    optionNameLabel.font = [UIFont systemFontOfSize:18];
    optionNameLabel.text = @"昼夜模式:";
    
    _nightTypeSeg = [[UISegmentedControl alloc] initWithItems:@[@"白天" , @"黑夜"]];
    _nightTypeSeg.frame = CGRectMake(160, (kTableViewCellHeight - 30)/2.0, 150, 30);
    _nightTypeSeg.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
    [_nightTypeSeg setTitleTextAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14]} forState:UIControlStateNormal];
    [_nightTypeSeg addTarget:self action:@selector(nightTypeSegmentedControlAction:) forControlEvents:UIControlEventValueChanged];
    
    [_nightTypeSeg setSelectedSegmentIndex:self.showNightType];
    
    [cell.contentView addSubview:optionNameLabel];
    [cell.contentView addSubview:_nightTypeSeg];
    
    return cell;
}

#pragma mark - UISegmentedControl Action

- (void)viewModeSegmentedControlAction:(id)sender
{
    NSInteger selectedIndex = [(UISegmentedControl *)sender selectedSegmentIndex];
    
    if (self.delegate && [self.delegate respondsToSelector:@selector(moreMenuViewTrackingModeChangeTo:)])
    {
        [self.delegate moreMenuViewTrackingModeChangeTo:(AMapNaviViewTrackingMode)selectedIndex];
    }
}

- (void)nightTypeSegmentedControlAction:(id)sender
{
    NSInteger selectedIndex = [(UISegmentedControl *)sender selectedSegmentIndex];
    
    if (self.delegate && [self.delegate respondsToSelector:@selector(moreMenuViewNightTypeChangeTo:)])
    {
        [self.delegate moreMenuViewNightTypeChangeTo:selectedIndex];
    }
}

#pragma mark - Finish Button Action

- (void)finishButtonAction:(id)sender
{
    if (self.delegate && [self.delegate respondsToSelector:@selector(moreMenuViewFinishButtonClicked)])
    {
        [self.delegate moreMenuViewFinishButtonClicked];
    }
}

至此,导航功能已经完结,如果感觉有帮助请打赏,欢迎评论、点赞哦!!!☺☺

上一篇下一篇

猜你喜欢

热点阅读