feat:增加途经点,完善规划,导航;

This commit is contained in:
xiaogg
2026-03-27 15:39:36 +08:00
parent 0123025296
commit 5843ef6e87
54 changed files with 2596 additions and 506 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -46,5 +46,6 @@ TODO: Add long description of the pod here.
s.dependency 'AMapNavi-NO-IDFA'
s.dependency 'AMapLocation-NO-IDFA'
s.dependency 'AMapSearch-NO-IDFA'
s.dependency 'MBProgressHUD'
end

Binary file not shown.

After

Width:  |  Height:  |  Size: 966 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -0,0 +1,17 @@
//
// ACustomAnnotationView.h
// AMapNavIOSSDK
//
// Created by admin on 2026/3/17.
//
#import <AMapNaviKit/AMapNaviKit.h>
#import "AMapNavCommonUtil.h"
NS_ASSUME_NONNULL_BEGIN
@interface ACustomAnnotationView : MAAnnotationView
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,177 @@
//
// ACustomAnnotationView.m
// AMapNavIOSSDK
//
// Created by admin on 2026/3/17.
//
#import "ACustomAnnotationView.h"
//
static const CGFloat kIconSize = 30; //
static const CGFloat kIconTextGap = 6.0; //
static const CGFloat kMaxTextWidth = 100.0; //
static const CGFloat kMaxTextLines = 2; //
static const CGFloat kVPad = 4.0; // centerOffset
@interface ACustomAnnotationView ()
@property (nonatomic, strong) UIImageView *iconView;
@property (nonatomic, strong) UILabel *titleLabel;
/// &
@property (nonatomic, assign) BOOL isAnnotationSelected;
@end
@implementation ACustomAnnotationView
#pragma mark - Init / Reuse
- (instancetype)initWithAnnotation:(id<MAAnnotation>)annotation
reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];
if (self) {
self.backgroundColor = [UIColor clearColor];
// MAAnnotationView image
self.image = nil;
[self _buildSubviews];
[self _updateFromAnnotation];
[self setNeedsLayout];
}
return self;
}
- (void)setAnnotation:(id<MAAnnotation>)annotation {
[super setAnnotation:annotation];
[self _updateFromAnnotation];
[self setNeedsLayout];
}
#pragma mark - Build
- (void)_buildSubviews {
//
if (!self.iconView) {
UIImageView *iv = [[UIImageView alloc] init];
iv.contentMode = UIViewContentModeScaleAspectFit;
[self addSubview:iv];
self.iconView = iv;
}
//
if (!self.titleLabel) {
UILabel *lbl = [[UILabel alloc] init];
lbl.numberOfLines = kMaxTextLines;
lbl.lineBreakMode = NSLineBreakByTruncatingTail;
lbl.textAlignment = NSTextAlignmentLeft;
[self addSubview:lbl];
self.titleLabel = lbl;
}
//
[self _applyStyle:NO];
}
/// &
- (void)_applyStyle:(BOOL)selected {
if (selected) {
self.iconView.image = [AMapNavCommonUtil imageWithName3x:@"station_select_icon"];
self.titleLabel.font = [UIFont boldSystemFontOfSize:14];
self.titleLabel.textColor = [UIColor colorWithWhite:0.12 alpha:1.0];
} else {
self.iconView.image = [AMapNavCommonUtil imageWithName3x:@"station_normal_icon"];
self.titleLabel.font = [UIFont systemFontOfSize:13];
self.titleLabel.textColor = [UIColor colorWithWhite:0.25 alpha:1.0];
}
}
#pragma mark - Data
- (void)_updateFromAnnotation {
NSString *text = nil;
id<MAAnnotation> ann = self.annotation;
if ([ann respondsToSelector:@selector(title)]) {
text = ann.title;
}
if (text.length == 0) {
text = @"加氢站";
}
self.titleLabel.text = text;
}
#pragma mark - SelectionMAAnnotationView
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
self.isAnnotationSelected = selected;
[self _applyStyle:selected];
[self setNeedsLayout];
}
#pragma mark - Layout
- (void)layoutSubviews {
[super layoutSubviews];
// 100pt 2
CGSize textConstraint = CGSizeMake(kMaxTextWidth,
CGFLOAT_MAX);
CGSize textFit = [self.titleLabel sizeThatFits:textConstraint];
// 2
CGFloat lineH = self.titleLabel.font.lineHeight;
CGFloat maxTextH = lineH * kMaxTextLines
+ self.titleLabel.font.leading * (kMaxTextLines - 1);
CGFloat textW = MIN(textFit.width, kMaxTextWidth);
CGFloat textH = MIN(textFit.height, maxTextH);
CGFloat totalW = kIconSize + kIconTextGap + textW;
CGFloat totalH = MAX(kIconSize, textH) + kVPad * 2;
// bounds
self.bounds = CGRectMake(0, 0, totalW, totalH);
//
CGFloat iconY = (totalH - kIconSize) * 0.5;
self.iconView.frame = CGRectMake(0, iconY, kIconSize, kIconSize);
//
CGFloat textY = (totalH - textH) * 0.5;
self.titleLabel.frame = CGRectMake(kIconSize + 1, textY, textW, textH);
//
// MAAnnotationView centerOffset (0,0)=
// totalH/2
self.centerOffset = CGPointMake(totalW / 2.0 - kIconSize / 2.0,
-(totalH / 2.0));
}
#pragma mark - Hit Test
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *hit = [super hitTest:point withEvent:event];
if (hit == self || [hit isDescendantOfView:self]) {
return self;
}
return hit;
}
#pragma mark - Touch
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
id<MAAnnotation> annotation = self.annotation;
if (!annotation) return;
UIView *sv = self.superview;
while (sv && ![sv isKindOfClass:[MAMapView class]]) {
sv = sv.superview;
}
MAMapView *mapView = (MAMapView *)sv;
if (!mapView) return;
// [mapView deselectAnnotation:annotation animated:NO];
}
@end

View File

@@ -8,5 +8,44 @@
#ifndef AMapNavSDKHeader_h
#define AMapNavSDKHeader_h
//#define kAMapSDKDebugFlag
// iPhone X
#define AMP_iPhoneX (UIApplication.sharedApplication.keyWindow.safeAreaInsets.bottom > 0 ? YES : NO)
// Status bar height.
#define AMP_StatusBarHeight (AMP_iPhoneX ? 44.f : 20.f)
// Navigation bar height.
#define AMP_NavigationBarHeight 44.f
// Tabbar height.
#define AMP_TabbarHeight (AMP_iPhoneX ? (49.f+34.f + 5) : 49.f)
// Tabbar safe bottom margin.
#define AMP_TabbarSafeBottomMargin (AMP_iPhoneX ? 34.f : 0.f)
#pragma mark - url
///获取站点列表
#define kGetStationListUrl @"https://beta-esg.api.lnh2e.com/appointment/station/getNearbyHydrogenStationsByLocation"
///单个站点详情
#define kGetStationDetailtUrl @"https://beta-esg.api.lnh2e.com/appointment/station/getStationInfoByArea"
///获取途经点
/**
请求方式post 暂时调不通
{
   "longitude":"121.254139",
    "latitude":"31.214628",
    "plateNumber":"浙F32111F",
"hydrogenSiteId":""//加氢站DI }
*/
#define kGetRoutePointtUrl @"https://beta-esg.api.lnh2e.com/appointment/truck/truckRouteAlgorithm"
#import "ANavPointModel.h"
#endif /* AMapNavSDKHeader_h */

View File

@@ -9,8 +9,6 @@
#import "ARoutePlaneController.h"
#define kAMapSDKDebugFlag
NS_ASSUME_NONNULL_BEGIN
@interface AMapNavSDKManager : NSObject

View File

@@ -13,6 +13,12 @@
#import <AMapNaviKit/AMapNaviKit.h>
#import "ACustomAnnotationView.h"
#import "AMapNavSDKHeader.h"
#import "ACustomPointAnnotation.h"
#import "ATripCalcResponse.h"
#import "AMapNavCommonUtil.h"
NS_ASSUME_NONNULL_BEGIN
@interface ARoutePlaneController : ABaseViewController

View File

@@ -45,7 +45,10 @@
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self.inputAddressTf becomeFirstResponder];
dispatch_async(dispatch_get_main_queue(), ^{
[self.inputAddressTf becomeFirstResponder];
});
}
-(void)initSubview {

View File

@@ -0,0 +1,55 @@
//
// AStationDetailPopupController.h
// AMapNavIOSSDK
//
// Created by admin on 2026/3/22.
//
#import <UIKit/UIKit.h>
#import "ANavPointModel.h"
#import "AMapNavSDKHeader.h"
NS_ASSUME_NONNULL_BEGIN
@class AStationDetailPopupController;
@protocol AStationDetailPopupDelegate <NSObject>
@optional
/// 点击"开始导航"
- (void)stationDetailPopupDidTapStartNavi:(AStationDetailPopupController *)popup;
/// 点击关闭
- (void)stationDetailPopupDidTapClose:(AStationDetailPopupController *)popup;
@end
@interface AStationDetailPopupController : UIViewController
@property (nonatomic, strong, nullable) ANavPointModel *pointModel;
/// 预计加氢费用(元),可由外部传入;若 nil 则隐藏
@property (nonatomic, copy, nullable) NSString *estimatedCost;
/// 预计时间,如 @"15分钟";若 nil 则隐藏
@property (nonatomic, copy, nullable) NSString *estimatedTime;
/// 行驶里程,如 @"23.5公里";若 nil 则隐藏
@property (nonatomic, copy, nullable) NSString *driveDistance;
/// 过路费,如 @"30元";若 nil 则隐藏
@property (nonatomic, copy, nullable) NSString *tollFee;
@property (nonatomic, weak, nullable) id<AStationDetailPopupDelegate> delegate;
/// 以半透明蒙层方式弹出在目标控制器上
- (void)presentInViewController:(UIViewController *)parentVC;
/// 关闭弹框
- (void)dismiss;
/// 关闭弹框,动画结束后执行 completion用于关闭后再 present 其他页面)
- (void)dismissWithCompletion:(nullable void(^)(void))completion;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,485 @@
//
// AStationDetailPopupController.m
// AMapNavIOSSDK
//
// Created by admin on 2026/3/22.
//
#import "AStationDetailPopupController.h"
#import "ABaseViewController.h"
#import "AMapNavCommonUtil.h"
#import <Masonry/Masonry.h>
// 绿
static inline UIColor *AStationThemeGreen(void) {
return [UIColor colorWithRed:0x1A/255.0 green:0x7C/255.0 blue:0x43/255.0 alpha:1.0];
}
@interface AStationDetailPopupController ()
///
@property (nonatomic, strong) UIControl *maskControl;
///
@property (nonatomic, strong) UIView *cardView;
///
@property (nonatomic, strong) UILabel *stationNameLabel;
///
@property (nonatomic, strong) UIImageView *costIconView;
@property (nonatomic, strong) UILabel *costLabel;
///
@property (nonatomic, strong) UILabel *addressLabel;
/// 线
@property (nonatomic, strong) UIView *separator;
///
@property (nonatomic, strong) UIImageView *timeIconView;
@property (nonatomic, strong) UILabel *timeLabel;
///
@property (nonatomic, strong) UIImageView *distanceIconView;
@property (nonatomic, strong) UILabel *distanceLabel;
///
@property (nonatomic, strong) UIImageView *tollIconView;
@property (nonatomic, strong) UILabel *tollLabel;
///
@property (nonatomic, strong) UIButton *closeButton;
///
@property (nonatomic, strong) UIButton *startNaviButton;
/// bottom constraint
@property (nonatomic, strong) MASConstraint *cardBottomConstraint;
@end
@implementation AStationDetailPopupController
#pragma mark - Life Cycle
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor clearColor];
[self _buildUI];
[self _setupMasonryConstraints];
[self _updateUI];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[self _playShowAnimation];
}
#pragma mark - Public
- (void)presentInViewController:(UIViewController *)parentVC {
self.modalPresentationStyle = UIModalPresentationOverCurrentContext;
self.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[parentVC presentViewController:self animated:NO completion:nil];
}
- (void)dismiss {
[self dismissWithCompletion:nil];
}
- (void)dismissWithCompletion:(void(^)(void))completion {
[self _playDismissAnimationWithCompletion:^{
[self dismissViewControllerAnimated:NO completion:completion];
}];
}
#pragma mark - Setter Override
- (void)setPointModel:(ANavPointModel *)pointModel {
_pointModel = pointModel;
if (self.isViewLoaded) [self _updateUI];
}
- (void)setEstimatedCost:(NSString *)estimatedCost {
_estimatedCost = [estimatedCost copy];
if (self.isViewLoaded) [self _updateUI];
}
- (void)setEstimatedTime:(NSString *)estimatedTime {
_estimatedTime = [estimatedTime copy];
if (self.isViewLoaded) [self _updateUI];
}
- (void)setDriveDistance:(NSString *)driveDistance {
_driveDistance = [driveDistance copy];
if (self.isViewLoaded) [self _updateUI];
}
- (void)setTollFee:(NSString *)tollFee {
_tollFee = [tollFee copy];
if (self.isViewLoaded) [self _updateUI];
}
#pragma mark - Build UI
/**
[]
-- 20pt
[icon] --
[icon] -- [icon] --
(30pt)
*/
- (void)_buildUI {
//
UIControl *mask = [[UIControl alloc] init];
mask.backgroundColor = [UIColor colorWithWhite:0 alpha:0.35];
[mask addTarget:self action:@selector(_onMaskTapped) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:mask];
self.maskControl = mask;
//
UIView *card = [[UIView alloc] init];
card.backgroundColor = [UIColor whiteColor];
card.layer.cornerRadius = 16;
card.layer.masksToBounds = NO;
card.layer.shadowColor = [UIColor blackColor].CGColor;
card.layer.shadowOpacity = 0.15;
card.layer.shadowRadius = 12;
card.layer.shadowOffset = CGSizeMake(0, -4);
[self.view addSubview:card];
self.cardView = card;
//
UIButton *closeBtn = [UIButton buttonWithType:UIButtonTypeCustom];
// [closeBtn setTitle:@"✕" forState:UIControlStateNormal];
[closeBtn setImage: [AMapNavCommonUtil imageWithName:@"icon_close"] forState:UIControlStateNormal];
[closeBtn setTitleColor:[UIColor colorWithWhite:0.5 alpha:1] forState:UIControlStateNormal];
closeBtn.titleLabel.font = [UIFont systemFontOfSize:16];
[closeBtn addTarget:self action:@selector(_onCloseTapped) forControlEvents:UIControlEventTouchUpInside];
[card addSubview:closeBtn];
self.closeButton = closeBtn;
//
UILabel *nameLabel = [[UILabel alloc] init];
nameLabel.font = [UIFont boldSystemFontOfSize:18];
nameLabel.textColor = [UIColor colorWithWhite:0.1 alpha:1];
nameLabel.numberOfLines = 2;
// nameLabel.adjustsFontSizeToFitWidth = YES;
nameLabel.minimumScaleFactor = 0.8;
[card addSubview:nameLabel];
self.stationNameLabel = nameLabel;
// 20pt
UILabel *costLabel = [[UILabel alloc] init];
costLabel.font = [UIFont systemFontOfSize:14];
costLabel.textColor = [UIColor colorWithWhite:0.2 alpha:1];
costLabel.numberOfLines = 1;
costLabel.textAlignment = NSTextAlignmentLeft;
// [costLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
// [costLabel setContentCompressionResistancePriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisHorizontal];
[card addSubview:costLabel];
self.costLabel = costLabel;
//
UILabel *addrLabel = [[UILabel alloc] init];
addrLabel.font = [UIFont systemFontOfSize:13];
addrLabel.textColor = [UIColor colorWithWhite:0.5 alpha:1];
addrLabel.numberOfLines = 2;
[card addSubview:addrLabel];
self.addressLabel = addrLabel;
UIImageView *costIcon = [[UIImageView alloc] init];
costIcon.contentMode = UIViewContentModeScaleAspectFit;
costIcon.image = [AMapNavCommonUtil imageWithName3x:@"ic_fuel"];
[card addSubview:costIcon];
self.costIconView = costIcon;
// 线
UIView *sep = [[UIView alloc] init];
sep.backgroundColor = [UIColor colorWithWhite:0.88 alpha:1];
[card addSubview:sep];
self.separator = sep;
//
UIImageView *timeIcon = [[UIImageView alloc] init];
timeIcon.contentMode = UIViewContentModeScaleAspectFit;
timeIcon.image = [AMapNavCommonUtil imageWithName3x:@"pre_time_icon"];
[card addSubview:timeIcon];
self.timeIconView = timeIcon;
//
UILabel *timeLabel = [[UILabel alloc] init];
timeLabel.font = [UIFont systemFontOfSize:14];
timeLabel.textColor = [UIColor colorWithWhite:0.2 alpha:1];
[card addSubview:timeLabel];
self.timeLabel = timeLabel;
//
UIImageView *distIcon = [[UIImageView alloc] init];
distIcon.contentMode = UIViewContentModeScaleAspectFit;
distIcon.image = [AMapNavCommonUtil imageWithName3x:@"pre_distance_icon"];
[card addSubview:distIcon];
self.distanceIconView = distIcon;
//
UILabel *distLabel = [[UILabel alloc] init];
distLabel.font = [UIFont systemFontOfSize:14];
distLabel.textColor = [UIColor colorWithWhite:0.2 alpha:1];
[card addSubview:distLabel];
self.distanceLabel = distLabel;
//
UIImageView *tollIcon = [[UIImageView alloc] init];
tollIcon.contentMode = UIViewContentModeScaleAspectFit;
tollIcon.image = [AMapNavCommonUtil imageWithName3x:@"pre_cost_icon"];
[card addSubview:tollIcon];
self.tollIconView = tollIcon;
//
UILabel *tollLabel = [[UILabel alloc] init];
tollLabel.font = [UIFont systemFontOfSize:14];
tollLabel.textColor = [UIColor colorWithWhite:0.2 alpha:1];
[card addSubview:tollLabel];
self.tollLabel = tollLabel;
//
UIButton *naviBtn = [UIButton buttonWithType:UIButtonTypeCustom];
[naviBtn setTitle:@"开始导航" forState:UIControlStateNormal];
[naviBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
naviBtn.titleLabel.font = [UIFont boldSystemFontOfSize:17];
naviBtn.backgroundColor = AStationThemeGreen();
naviBtn.layer.cornerRadius = 24;
[naviBtn addTarget:self action:@selector(_onStartNaviTapped) forControlEvents:UIControlEventTouchUpInside];
[card addSubview:naviBtn];
self.startNaviButton = naviBtn;
}
#pragma mark - Masonry Constraints
- (void)_setupMasonryConstraints {
UIView *card = self.cardView;
CGFloat iconSize = 16;
//
[self.maskControl mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self.view);
}];
// 16 safeArea 30pt
// top bottom
[card mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.view).offset(16);
make.right.equalTo(self.view).offset(-16);
// =
make.top.equalTo(self.view.mas_bottom).offset(0);
}];
//
[self.closeButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(card).offset(8);
make.right.equalTo(card).offset(-15);
make.width.height.mas_equalTo(40);
}];
// + nameLabel20pt
// nameLabel55%
[self.stationNameLabel setContentHuggingPriority:UILayoutPriorityDefaultLow
forAxis:UILayoutConstraintAxisHorizontal];
[self.stationNameLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(card).offset(25);
make.left.equalTo(card).offset(16);
// make.width.lessThanOrEqualTo(card).multipliedBy(0.45);
make.right.equalTo(self.closeButton.mas_left).offset(-12);
}];
// 6pt
[self.addressLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.stationNameLabel.mas_bottom).offset(10);
make.left.equalTo(card).offset(16);
make.right.equalTo(card).offset(-16);
}];
// 线12pt
[self.separator mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.addressLabel.mas_bottom).offset(15);
make.left.equalTo(card).offset(16);
make.right.equalTo(card).offset(-16);
make.height.mas_equalTo(0.5);
}];
// 线14pt
[self.timeIconView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.separator.mas_bottom).offset(15);
make.left.equalTo(card).offset(16);
make.width.height.mas_equalTo(iconSize);
}];
[self.timeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.timeIconView);
make.left.equalTo(self.timeIconView.mas_right).offset(6);
// make.right.equalTo(card).offset(-16);
make.height.mas_equalTo(24);
}];
///cost
[self.costIconView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.timeIconView);
make.left.equalTo(self.timeLabel.mas_right).offset(30);
make.width.height.mas_equalTo(iconSize);
}];
[self.costLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.costIconView);
make.left.equalTo(self.costIconView.mas_right).offset(6);
make.right.lessThanOrEqualTo(card).offset(-10);
}];
// + 12pt
[self.distanceIconView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.timeIconView.mas_bottom).offset(15);
make.left.equalTo(card).offset(16);
make.width.height.mas_equalTo(iconSize);
}];
[self.distanceLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.distanceIconView);
make.left.equalTo(self.distanceIconView.mas_right).offset(6);
//
make.width.mas_lessThanOrEqualTo(130);
make.height.mas_equalTo(24);
}];
[self.tollIconView mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.distanceIconView);
make.left.equalTo(self.costIconView.mas_left);
make.width.height.mas_equalTo(iconSize);
}];
[self.tollLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.distanceIconView);
make.left.equalTo(self.tollIconView.mas_right).offset(6);
// make.right.equalTo(card).offset(-16);
make.height.mas_equalTo(24);
}];
// 18pt30pt
[self.startNaviButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.distanceIconView.mas_bottom).offset(50);
make.left.equalTo(card).offset(16);
make.right.equalTo(card).offset(-16);
make.height.mas_equalTo(48);
make.bottom.equalTo(card).offset(-AMP_TabbarSafeBottomMargin); // 30pt
}];
}
#pragma mark - Data Update
- (void)_updateUI {
self.stationNameLabel.text = (self.pointModel.name.length > 0)
? self.pointModel.name : @"--";
self.costLabel.text = (self.estimatedCost.length > 0)
? [NSString stringWithFormat:@"预计加氢费用:%@元", self.estimatedCost]
: @"预计加氢费用:--元";
self.addressLabel.text = (self.pointModel.address.length > 0)
? self.pointModel.address : @"--";
// "-- 分钟"
self.timeLabel.text = (self.estimatedTime.length > 0)
? [NSString stringWithFormat:@"预计时间:%@分钟", self.estimatedTime]
: @"预计时间:--分钟";
// "-- 公里"
self.distanceLabel.text = (self.driveDistance.length > 0)
? [NSString stringWithFormat:@"行驶里程:%@公里", self.driveDistance]
: @"行驶里程:--公里";
// "-- 元"
self.tollLabel.text = (self.tollFee.length > 0)
? [NSString stringWithFormat:@"过路费:%@元", self.tollFee]
: @"过路费:--元";
}
#pragma mark - Animation
/**
top 30pt safeArea
*/
- (void)_playShowAnimation {
// safeArea 30pt
[self.cardView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.view).offset(0);
make.right.equalTo(self.view).offset(-0);
make.bottom.equalTo(self.view).offset(0);
}];
self.maskControl.alpha = 0;
[UIView animateWithDuration:0.36
delay:0
usingSpringWithDamping:0.82
initialSpringVelocity:0.5
options:UIViewAnimationOptionCurveEaseOut
animations:^{
self.maskControl.alpha = 1;
[self.view layoutIfNeeded];
} completion:nil];
}
- (void)_playDismissAnimationWithCompletion:(void(^)(void))completion {
[self.cardView mas_remakeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.view).offset(16);
make.right.equalTo(self.view).offset(-16);
make.top.equalTo(self.view.mas_bottom).offset(20);
}];
[UIView animateWithDuration:0.25
delay:0
options:UIViewAnimationOptionCurveEaseIn
animations:^{
self.maskControl.alpha = 0;
[self.view layoutIfNeeded];
} completion:^(BOOL finished) {
if (completion) completion();
}];
}
#pragma mark - Actions
- (void)_onMaskTapped {
if ([self.delegate respondsToSelector:@selector(stationDetailPopupDidTapClose:)]) {
[self.delegate stationDetailPopupDidTapClose:self];
}
[self dismiss];
}
- (void)_onCloseTapped {
if ([self.delegate respondsToSelector:@selector(stationDetailPopupDidTapClose:)]) {
[self.delegate stationDetailPopupDidTapClose:self];
}
[self dismiss];
}
- (void)_onStartNaviTapped {
// delegate
// presentViewController
__weak typeof(self) weakSelf = self;
[self dismissWithCompletion:^{
__strong typeof(weakSelf) strongSelf = weakSelf;
if ([strongSelf.delegate respondsToSelector:@selector(stationDetailPopupDidTapStartNavi:)]) {
[strongSelf.delegate stationDetailPopupDidTapStartNavi:strongSelf];
}
}];
}
@end

View File

@@ -0,0 +1,67 @@
//
// AAlgorithmPathModel.h
// AMapNavIOSSDK
//
// Created by admin on 2026/3/25.
//
#import <Foundation/Foundation.h>
#import <MJExtension/MJExtension.h>
NS_ASSUME_NONNULL_BEGIN
@interface AAlgorithmPathModel : NSObject
/// 单程
@property (nonatomic, copy, nullable) NSString *tripRecommendationId;
@property (nonatomic, copy, nullable) NSString *staId;
@property (nonatomic, copy, nullable) NSString *tripOneWayPathId;
@property (nonatomic, copy, nullable) NSString *tripReturnPathId;
/// 里程(公里)
@property (nonatomic, copy, nullable) NSString *oneWayDis;
@property (nonatomic, copy, nullable) NSString *returnDis;
@property (nonatomic, copy, nullable) NSString *roundTripDis;
/// 时长(分钟)
@property (nonatomic, copy, nullable) NSString *oneWayTime;
@property (nonatomic, copy, nullable) NSString *returnTime;
@property (nonatomic, copy, nullable) NSString *roundTripTime;
/// 总成本(元)
@property (nonatomic, copy, nullable) NSString *oneWayCost;
@property (nonatomic, copy, nullable) NSString *returnCost;
@property (nonatomic, copy, nullable) NSString *roundTripCost;
/// 人工成本(元)
@property (nonatomic, copy, nullable) NSString *oneWayLaborCost;
@property (nonatomic, copy, nullable) NSString *returnLaborCost;
@property (nonatomic, copy, nullable) NSString *roundTripLaborCost;
/// 高速成本(元)
@property (nonatomic, copy, nullable) NSString *oneWayChargerouteCost;
@property (nonatomic, copy, nullable) NSString *returnChargerouteCost;
@property (nonatomic, copy, nullable) NSString *roundTripChargerouteCost;
/// 氢耗(公斤)
@property (nonatomic, copy, nullable) NSString *oneWayHydrogenConsumption;
@property (nonatomic, copy, nullable) NSString *returnLaborHydrogenConsumption;
@property (nonatomic, copy, nullable) NSString *roundTripHydrogenConsumption;
/// 氢气成本(元)
@property (nonatomic, copy, nullable) NSString *oneWayHydrogenCost;
@property (nonatomic, copy, nullable) NSString *returnLaborHydrogenCost;
@property (nonatomic, copy, nullable) NSString *roundTripHydrogenCost;
/// 加氢站相关
@property (nonatomic, copy, nullable) NSString *hydrogenCost; // 氢气总成本(元)
@property (nonatomic, copy, nullable) NSString *hydrogenStaServiceTime; // 站服务总时长(分钟)
@property (nonatomic, copy, nullable) NSString *hydrogenStaRefuelingTime;// 实际加油时长(分钟)
@property (nonatomic, copy, nullable) NSString *hydrogenStaQueueTime; // 排队时长(分钟)
@property (nonatomic, copy, nullable) NSString *hydrogenStaServiceTimeCost; // 站服务时间成本(元)
@property (nonatomic, copy, nullable) NSString *hydrogenStaRefuelingTimeCost;// 加油时间成本(元)
@property (nonatomic, copy, nullable) NSString *hydrogenStaQueueTimeCost; // 排队时间成本(元)
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,12 @@
//
// AAlgorithmPathModel.m
// AMapNavIOSSDK
//
// Created by admin on 2026/3/25.
//
#import "AAlgorithmPathModel.h"
@implementation AAlgorithmPathModel
@end

View File

@@ -0,0 +1,17 @@
//
// ACustomPointAnnotation.h
// Pods
//
// Created by admin on 2026/3/25.
//
#import <AMapNaviKit/AMapNaviKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface ACustomPointAnnotation : MAPointAnnotation
@property (nonatomic, copy, nullable) NSString *stationID;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,12 @@
//
// ACustomPointAnnotation.m
// Pods
//
// Created by admin on 2026/3/25.
//
#import "ACustomPointAnnotation.h"
@implementation ACustomPointAnnotation
@end

View File

@@ -34,6 +34,8 @@ NS_ASSUME_NONNULL_BEGIN
*/
@interface AMapHyStationModel : NSObject
@property (nonatomic, copy, nullable) NSString *ID;
@property (nonatomic, copy, nullable) NSString *hydrogenId;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy, nullable) NSString *shortName;
@property (nonatomic, copy, nullable) NSString *siteNo;

View File

@@ -8,6 +8,10 @@
#import "AMapHyStationModel.h"
@implementation AMapHyStationModel
+ (NSDictionary *)mj_replacedKeyFromPropertyName
{
return @{ @"ID" : @"id"};
}
@end

View File

@@ -0,0 +1,26 @@
//
// ANavPointModel.h
// AMapNavIOSSDK
//
// Created by admin on 2026/3/25.
//
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
NS_ASSUME_NONNULL_BEGIN
@interface ANavPointModel : NSObject
@property (nonatomic, copy, nullable) NSString *name;
@property (nonatomic, copy, nullable) NSString *address;
@property (nonatomic, copy, nullable) NSString *stationID;
///经纬度
@property (nonatomic, assign) CLLocationCoordinate2D coordinate;
///初始化
+ (instancetype)instanceWithCoordinate:(CLLocationCoordinate2D)coordinate name:(NSString *)name address:(NSString *)address;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,22 @@
//
// ANavPointModel.m
// AMapNavIOSSDK
//
// Created by admin on 2026/3/25.
//
#import "ANavPointModel.h"
@implementation ANavPointModel
///
+ (instancetype)instanceWithCoordinate:(CLLocationCoordinate2D)coordinate name:(NSString *)name address:(NSString *)address {
ANavPointModel *instance = [[ANavPointModel alloc] init];
if (instance) {
instance.coordinate = coordinate;
instance.name = name;
instance.address = address;
}
return instance;
}
@end

View File

@@ -0,0 +1,32 @@
//
// ANaviPathInfoModel.h
// AMapNavIOSSDK
//
// Created by admin on 2026/3/25.
//
#import <Foundation/Foundation.h>
#import <MJExtension/MJExtension.h>
NS_ASSUME_NONNULL_BEGIN
/**
{
"name": "浙江省嘉兴市平湖市乍浦镇滨海大道中国石化滨海大道加油加气站",
"poiId": "",
"coordinate": {
"longitude": "121.070434",
"latitude": "30.596124"
}
}
*/
@interface ANaviPathInfoModel : NSObject
@property (nonatomic, copy, nullable) NSString *name;
@property (nonatomic, copy, nullable) NSString *poiId;
@property (nonatomic, copy, nullable) NSString *longitude;
@property (nonatomic, copy, nullable) NSString *latitude;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,20 @@
//
// ANaviPathInfoModel.m
// AMapNavIOSSDK
//
// Created by admin on 2026/3/25.
//
#import "ANaviPathInfoModel.h"
@implementation ANaviPathInfoModel
+ (NSDictionary *)mj_replacedKeyFromPropertyName {
// JSON coordinate longitude/latitude
return @{
@"longitude": @"coordinate.longitude",
@"latitude": @"coordinate.latitude"
};
}
@end

View File

@@ -0,0 +1,29 @@
//
// APathModel.h
// AMapNavIOSSDK
//
// Created by admin on 2026/3/25.
//
#import <Foundation/Foundation.h>
#import <MJExtension/MJExtension.h>
#import "ANaviPathInfoModel.h"
NS_ASSUME_NONNULL_BEGIN
@class ANaviPathInfoModel;
@interface APathModel : NSObject
@property (nonatomic, assign) CGFloat distance; // 总距离(米)
@property (nonatomic, assign) CGFloat duration; // 总时长(秒)
@property (nonatomic, copy, nullable) NSString *strategy; // 路线策略,如"避免拥堵"
@property (nonatomic, copy, nullable) NSString *tolls; // 高速费(元)
@property (nonatomic, assign) CGFloat toll_distance; // 高速里程(米)
@property (nonatomic, assign) NSInteger restriction; // 限行标志,-1 无
@property (nonatomic, assign) NSInteger traffic_lights; // 红绿灯数量
@property (nonatomic, strong) NSArray<ANaviPathInfoModel *> *naviList; // 途经点列表
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,17 @@
//
// APathModel.m
// AMapNavIOSSDK
//
// Created by admin on 2026/3/25.
//
#import "APathModel.h"
#import "ANaviPathInfoModel.h"
@implementation APathModel
+ (NSDictionary *)mj_objectClassInArray {
return @{@"naviList": [ANaviPathInfoModel class]};
}
@end

View File

@@ -0,0 +1,64 @@
//
// ASiteModel.h
// AMapNavIOSSDK
//
// Created by admin on 2026/3/25.
//
#import <Foundation/Foundation.h>
#import <MJExtension/MJExtension.h>
NS_ASSUME_NONNULL_BEGIN
/**
{
"innerSiteId": "202304241822210001",
"name": "滨海大道加油加气站",
"shortName": "滨海",
"siteNo": "000001",
"city": "浙江省-嘉兴市",
"address": "嘉兴市平湖市滨海大道1515号",
"contact": "陆平",
"phone": "18666666666",
"type": "",
"coOpMode": "签约",
"booking": "无需预约",
"siteStatus": "0",
"siteStatusName": "营运中",
"startBusiness": "08:00:00",
"endBusiness": "20:00:00",
"billingMethod": "月付款",
"term": "1703952000000",
"remark": "",
"longitude": "121.07112700",
"latitude": "30.59577700",
"distance": ""
}
*/
@interface ASiteModel : NSObject
@property (nonatomic, copy, nullable) NSString *innerSiteId;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy, nullable) NSString *shortName;
@property (nonatomic, copy, nullable) NSString *siteNo;
@property (nonatomic, copy, nullable) NSString *city;
@property (nonatomic, copy, nullable) NSString *address;
@property (nonatomic, copy, nullable) NSString *contact;
@property (nonatomic, copy, nullable) NSString *phone;
@property (nonatomic, copy, nullable) NSString *type;
@property (nonatomic, copy, nullable) NSString *coOpMode;
@property (nonatomic, copy, nullable) NSString *booking;
@property (nonatomic, copy, nullable) NSString *siteStatus;
@property (nonatomic, copy, nullable) NSString *siteStatusName;
@property (nonatomic, copy, nullable) NSString *startBusiness;
@property (nonatomic, copy, nullable) NSString *endBusiness;
@property (nonatomic, copy, nullable) NSString *billingMethod;
@property (nonatomic, copy, nullable) NSString *term;
@property (nonatomic, copy, nullable) NSString *remark;
@property (nonatomic, copy, nullable) NSString *longitude;
@property (nonatomic, copy, nullable) NSString *latitude;
@property (nonatomic, copy, nullable) NSString *distance;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,12 @@
//
// ASiteModel.m
// AMapNavIOSSDK
//
// Created by admin on 2026/3/25.
//
#import "ASiteModel.h"
@implementation ASiteModel
@end

View File

@@ -0,0 +1,65 @@
//
// ATripCalcResponse.h
// AMapNavIOSSDK
//
// Created by admin on 2026/3/25.
//
#import <Foundation/Foundation.h>
#import <MJExtension/MJExtension.h>
#import "AAlgorithmPathModel.h"
#import "APathModel.h"
#import "ASiteModel.h"
#import "ANaviPathInfoModel.h"
#import "ATruckModel.h"
NS_ASSUME_NONNULL_BEGIN
@class ATruckModel;
@class ASiteModel;
@class APathModel;
@class AAlgorithmPathModel;
#pragma mark - data 节点
/**
{
"truckDto": { ... },
"truckDtoStr": null,
"destinationSite": { ... },
"pathDto": { ... },
"algorithmPath": { ... },
"isInvokeAlgorithm": true
}
*/
@interface ATripCalcDataModel : NSObject
@property (nonatomic, strong, nullable) ATruckModel *truckDto;
@property (nonatomic, copy, nullable) NSString *truckDtoStr;
@property (nonatomic, strong, nullable) ASiteModel *destinationSite;
@property (nonatomic, strong, nullable) APathModel *pathDto;
@property (nonatomic, strong, nullable) AAlgorithmPathModel *algorithmPath;
@property (nonatomic, assign) BOOL isInvokeAlgorithm;
@end
#pragma mark - 根响应
/**
{
"code": 200,
"msg": "操作成功!",
"data": { ... }
}
*/
@interface ATripCalcResponse : NSObject
@property (nonatomic, assign) NSInteger code;
@property (nonatomic, copy, nullable) NSString *msg;
@property (nonatomic, strong, nullable) ATripCalcDataModel *data;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,33 @@
//
// ATripCalcResponse.m
// AMapNavIOSSDK
//
// Created by admin on 2026/3/25.
//
#import "ATripCalcResponse.h"
#import "ATruckModel.h"
#import "ASiteModel.h"
#import "APathModel.h"
#import "AAlgorithmPathModel.h"
@implementation ATripCalcDataModel
+ (NSDictionary *)mj_objectClassInArray {
return @{
@"truckDto": [ATruckModel class],
@"destinationSite": [ASiteModel class],
@"pathDto": [APathModel class],
@"algorithmPath": [AAlgorithmPathModel class]
};
}
@end
@implementation ATripCalcResponse
+ (NSDictionary *)mj_objectClassInArray {
return @{@"data":[ATripCalcDataModel class]};
}
@end

View File

@@ -0,0 +1,58 @@
//
// ATruckModel.h
// AMapNavIOSSDK
//
// Created by admin on 2026/3/25.
//
#import <Foundation/Foundation.h>
#import <MJExtension/MJExtension.h>
NS_ASSUME_NONNULL_BEGIN
/**
{
"isRestriction": true,
"mvehicleSizeName": "重型货车",
"mvehicleAxisUnit": "轴",
"mcarNumber": "浙F32111F",
"mcarType": 0,
"mvehicleHeight": "3.8",
"mvehicleHeightUnit": "M",
"mvehicleWeight": null,
"mvehicleWeightUnit": "T",
"mvehicleLoad": "49.0",
"mvehicleLoadUnit": "T",
"mvehicleLoadSwitch": false,
"mvehicleWidth": "0.0",
"mvehicleWidthUnit": "M",
"mvehicleLength": "7.6",
"mvehicleLengthUnit": "M",
"mvehicleSize": 4,
"mvehicleAxis": 5
}
*/
@interface ATruckModel : NSObject
@property (nonatomic, assign) BOOL isRestriction;
@property (nonatomic, copy, nullable) NSString *mvehicleSizeName;
@property (nonatomic, copy, nullable) NSString *mvehicleAxisUnit;
@property (nonatomic, copy, nullable) NSString *mcarNumber;
@property (nonatomic, assign) NSInteger mcarType;
@property (nonatomic, copy, nullable) NSString *mvehicleHeight;
@property (nonatomic, copy, nullable) NSString *mvehicleHeightUnit;
@property (nonatomic, copy, nullable) NSString *mvehicleWeight;
@property (nonatomic, copy, nullable) NSString *mvehicleWeightUnit;
@property (nonatomic, copy, nullable) NSString *mvehicleLoad;
@property (nonatomic, copy, nullable) NSString *mvehicleLoadUnit;
@property (nonatomic, assign) BOOL mvehicleLoadSwitch;
@property (nonatomic, copy, nullable) NSString *mvehicleWidth;
@property (nonatomic, copy, nullable) NSString *mvehicleWidthUnit;
@property (nonatomic, copy, nullable) NSString *mvehicleLength;
@property (nonatomic, copy, nullable) NSString *mvehicleLengthUnit;
@property (nonatomic, assign) NSInteger mvehicleSize;
@property (nonatomic, assign) NSInteger mvehicleAxis;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,12 @@
//
// ATruckModel.m
// AMapNavIOSSDK
//
// Created by admin on 2026/3/25.
//
#import "ATruckModel.h"
@implementation ATruckModel
@end

View File

@@ -6,13 +6,33 @@
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface AMapNavCommonUtil : NSObject
+(UIImage *)imageWithName:(NSString *)name;
/// 显示加载转圈nil 消息时不显示文字)
+ (void)showLoadingWithMsg:(nullable NSString *)msg;
/// 关闭所有 MBProgressHUD
+ (void)dismiss;
/// 显示提示,自动 2.0s 后消失
+ (void)showMsg:(NSString *)msg;
/// 获取图片2x
+ (UIImage *)imageWithName:(NSString *)name;
/// 获取图片3x
+ (UIImage *)imageWithName3x:(NSString *)name;
/// 判断字符串是否为空
BOOL stringIsEmpty(NSString *str);
/// 判断字符串是否非空
BOOL stringIsNotEmpty(NSString *str);
@end

View File

@@ -6,9 +6,117 @@
//
#import "AMapNavCommonUtil.h"
#import <MBProgressHUD/MBProgressHUD.h>
/// HUD
static MBProgressHUD *_sharedHUD = nil;
@implementation AMapNavCommonUtil
#pragma mark - MBProgressHUD
+ (UIWindow *)_keyWindow {
if (@available(iOS 13.0, *)) {
for (UIWindowScene *scene in [UIApplication sharedApplication].connectedScenes) {
if (scene.activationState == UISceneActivationStateForegroundActive) {
for (UIWindow *window in scene.windows) {
if (window.isKeyWindow) return window;
}
}
}
}
return [UIApplication sharedApplication].keyWindow;
}
+ (void)showLoadingWithMsg:(NSString *)msg {
dispatch_async(dispatch_get_main_queue(), ^{
// [self dismiss];
UIWindow *window = [self _keyWindow];
if (!window) return;
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:window animated:YES];
hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor;
hud.bezelView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.75];
hud.contentColor = [UIColor whiteColor];
if (msg.length > 0) {
hud.label.text = msg;
hud.label.font = [UIFont systemFontOfSize:14];
}
hud.removeFromSuperViewOnHide = YES;
_sharedHUD = hud;
});
}
+ (void)dismiss {
dispatch_async(dispatch_get_main_queue(), ^{
if (_sharedHUD) {
[_sharedHUD hideAnimated:YES];
_sharedHUD = nil;
} else {
// HUD
UIWindow *window = [self _keyWindow];
if (window) {
[MBProgressHUD hideHUDForView:window animated:YES];
}
}
});
}
+ (void)showMsg:(NSString *)msg {
if (msg.length == 0) return;
dispatch_async(dispatch_get_main_queue(), ^{
UIWindow *window = [self _keyWindow];
if (!window) return;
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:window animated:YES];
hud.mode = MBProgressHUDModeText;
hud.bezelView.style = MBProgressHUDBackgroundStyleSolidColor;
hud.bezelView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.75];
hud.contentColor = [UIColor whiteColor];
hud.label.text = msg;
hud.label.font = [UIFont systemFontOfSize:14];
hud.removeFromSuperViewOnHide = YES;
// 2.0s
[hud hideAnimated:YES afterDelay:2.0];
});
}
#pragma mark -
BOOL stringIsEmpty (NSString *str)
{
if (str == nil || str == NULL)
{
return YES;
}
if ([str isKindOfClass:[NSNull class]])
{
return YES;
}
if ([str isKindOfClass:[NSString class]])
{
NSString * newStr = [str stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSSet *emptySet = [NSSet setWithObjects:@"", @"null", @"(null)", @"<null>", @"NULL", @"无",@"kZero", nil];
if ([emptySet containsObject:str] || [emptySet containsObject:newStr]) {
return YES;
} else {
return [newStr length] == 0;
}
}
return NO;
}
BOOL stringIsNotEmpty (NSString *str)
{
return ! stringIsEmpty(str);
}
#pragma mark -
+(UIImage *)imageWithName:(NSString *)name {
@@ -22,6 +130,15 @@
return arrowImage;
}
+(UIImage *)imageWithName3x:(NSString *)name {
NSURL * url = [[NSBundle mainBundle] URLForResource:@"AMapNavIOSSDK" withExtension:@"bundle"];
NSBundle *containnerBundle = [NSBundle bundleWithURL:url];
NSString * path = [containnerBundle pathForResource:[NSString stringWithFormat:@"%@@3x.png" , name] ofType:nil];
UIImage * arrowImage = [[UIImage imageWithContentsOfFile:path] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
return arrowImage;
}
@end

View File

@@ -9,16 +9,16 @@
#import <Foundation/Foundation.h>
#import <AMapNaviKit/MAMapKit.h>
@interface SelectableOverlay : MABaseOverlay
/// 继承 MAPolyline自身就是 Polylinerenderer 用 self 初始化不会产生 overlay 不匹配警告
@interface SelectableOverlay : MAPolyline
@property (nonatomic, assign) NSInteger routeID;
@property (nonatomic, assign, getter = isSelected) BOOL selected;
@property (nonatomic, strong) UIColor * selectedColor;
@property (nonatomic, strong) UIColor * regularColor;
@property (nonatomic, strong) UIColor *selectedColor;
@property (nonatomic, strong) UIColor *regularColor;
@property (nonatomic, strong) id<MAOverlay> overlay;
- (id)initWithOverlay:(id<MAOverlay>) overlay;
/// 用坐标数组和数量初始化(对应原来的 MAPolyline polylineWithCoordinates:count:
+ (instancetype)overlayWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count;
@end

View File

@@ -10,32 +10,14 @@
@implementation SelectableOverlay
#pragma mark - MAOverlay Protocol
- (CLLocationCoordinate2D)coordinate
+ (instancetype)overlayWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count
{
return [self.overlay coordinate];
}
- (MAMapRect)boundingMapRect
{
return [self.overlay boundingMapRect];
}
#pragma mark - Life Cycle
- (id)initWithOverlay:(id<MAOverlay>)overlay
{
self = [super init];
if (self)
{
self.overlay = overlay;
self.selected = NO;
self.selectedColor = [UIColor colorWithRed:0.05 green:0.39 blue:0.9 alpha:0.8];
self.regularColor = [UIColor colorWithRed:0.5 green:0.6 blue:0.9 alpha:0.8];
}
return self;
// MAPolyline SelectableOverlay
SelectableOverlay *overlay = (SelectableOverlay *)[super polylineWithCoordinates:coords count:count];
overlay.selected = NO;
overlay.selectedColor = [UIColor colorWithRed:0.05 green:0.39 blue:0.9 alpha:0.8];
overlay.regularColor = [UIColor colorWithRed:0.5 green:0.6 blue:0.9 alpha:0.8];
return overlay;
}
@end

View File

@@ -0,0 +1,32 @@
//
// ABottomBarView.h
// AMapNavIOSSDK
//
// Created by admin on 2026/3/25.
//
#import <UIKit/UIKit.h>
#import "AMapNavSDKHeader.h"
NS_ASSUME_NONNULL_BEGIN
@class ABottomBarView;
@protocol ABottomBarViewDelegate <NSObject>
/// 点击「规划路线」按钮
- (void)bottomBarViewDidTapCalRoute:(ABottomBarView *)barView;
/// 输入框开始编辑(外部弹起搜索页)
- (void)bottomBarViewDidTapSearchField:(ABottomBarView *)barView;
@end
/// 底部搜索+规划路线栏
@interface ABottomBarView : UIView
@property (nonatomic, weak) id<ABottomBarViewDelegate> delegate;
/// 目的地文本(外部赋值后自动更新输入框)
@property (nonatomic, copy, nullable) NSString *destinationText;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,204 @@
//
// ABottomBarView.m
// AMapNavIOSSDK
//
// Created by admin on 2026/3/25.
//
#import "ABottomBarView.h"
#import "AMapNavCommonUtil.h"
#import <Masonry/Masonry.h>
// 绿
static inline UIColor *ABottomBarThemeGreen(void) {
return [UIColor colorWithRed:0x1A/255.0 green:0x6E/255.0 blue:0x45/255.0 alpha:1.0];
}
@interface ABottomBarView () <UITextFieldDelegate>
///
@property (nonatomic, strong) UIView *cardView;
///
@property (nonatomic, strong) UIImageView *searchIconView;
///
@property (nonatomic, strong) UITextField *searchField;
/// 线
@property (nonatomic, strong) UIButton *calRouteButton;
@end
@implementation ABottomBarView
#pragma mark - Init
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor clearColor];
[self _buildUI];
}
return self;
}
- (instancetype)init {
return [self initWithFrame:CGRectZero];
}
#pragma mark - Build UI
- (void)_buildUI {
//
UIView *card = [[UIView alloc] init];
// card.backgroundColor = [UIColor colorWithRed:0.96 green:0.97 blue:0.98 alpha:0.96];
card.backgroundColor = [UIColor whiteColor];
card.layer.cornerRadius = 16;
//
card.layer.shadowColor = [UIColor blackColor].CGColor;
card.layer.shadowOpacity = 0.10;
card.layer.shadowRadius = 10;
card.layer.shadowOffset = CGSizeMake(0, -3);
card.layer.masksToBounds = NO;
[self addSubview:card];
self.cardView = card;
[card mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.equalTo(self);
}];
//
UIView *searchRow = [[UIView alloc] init];
searchRow.backgroundColor = [UIColor whiteColor];
searchRow.layer.cornerRadius = 5;
searchRow.layer.masksToBounds = YES;
searchRow.layer.borderColor = [UIColor colorWithRed:0.95 green:0.95 blue:0.95 alpha:1].CGColor;
searchRow.layer.borderWidth = 1;
[card addSubview:searchRow];
[searchRow mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(card).offset(-18);
make.left.equalTo(card).offset(16);
make.right.equalTo(card).offset(-16);
make.height.mas_equalTo(50);
}];
//
UIImageView *searchIcon = [[UIImageView alloc] init];
searchIcon.contentMode = UIViewContentModeScaleAspectFit;
searchIcon.image = [AMapNavCommonUtil imageWithName3x:@"search_icon"];
[searchRow addSubview:searchIcon];
self.searchIconView = searchIcon;
[searchIcon mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(searchRow);
make.left.equalTo(searchRow).offset(12);
make.width.height.mas_equalTo(18);
}];
//
UITextField *field = [[UITextField alloc] init];
field.placeholder = @"请输入目的地,不输入则自动匹配附近成本最低加氢站";
field.font = [UIFont systemFontOfSize:14];
field.textColor = [UIColor colorWithWhite:0.1 alpha:1];
field.borderStyle = UITextBorderStyleNone;
field.backgroundColor = [UIColor clearColor];
field.delegate = self;
// placeholder
if (field.placeholder) {
field.attributedPlaceholder = [[NSAttributedString alloc]
initWithString:field.placeholder
attributes:@{NSForegroundColorAttributeName:
[UIColor colorWithWhite:0.65 alpha:1],
NSFontAttributeName:
[UIFont systemFontOfSize:13]}];
}
[searchRow addSubview:field];
self.searchField = field;
[field mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(searchRow);
make.left.equalTo(searchIcon.mas_right).offset(8);
make.right.equalTo(searchRow).offset(-12);
make.top.bottom.equalTo(searchRow);
}];
// 线
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.backgroundColor = ABottomBarThemeGreen();
btn.layer.cornerRadius = 24;
btn.layer.masksToBounds = YES;
//
UIImageView *routeIcon = [[UIImageView alloc] init];
routeIcon.contentMode = UIViewContentModeScaleAspectFit;
routeIcon.image = [AMapNavCommonUtil imageWithName3x:@"cal_ruoute_icon"];
routeIcon.userInteractionEnabled = NO;
[btn addSubview:routeIcon];
//
UILabel *titleLbl = [[UILabel alloc] init];
titleLbl.text = @"规划路线";
titleLbl.textColor = [UIColor whiteColor];
titleLbl.font = [UIFont boldSystemFontOfSize:16];
titleLbl.userInteractionEnabled = NO;
[btn addSubview:titleLbl];
//
[routeIcon mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(btn);
make.right.equalTo(titleLbl.mas_left).offset(-8);
make.width.height.mas_equalTo(22);
}];
[titleLbl mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(btn);
// titleLbl (22+8)/2 = 15pt
make.centerX.equalTo(btn).offset(15);
}];
[btn addTarget:self action:@selector(_onCalRouteTapped) forControlEvents:UIControlEventTouchUpInside];
[card addSubview:btn];
self.calRouteButton = btn;
CGFloat off_y = AMP_TabbarHeight;
#ifdef kAMapSDKDebugFlag
off_y = 0;
#endif
[btn mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(searchRow.mas_bottom).offset(20);
make.left.equalTo(card).offset(16);
make.right.equalTo(card).offset(-16);
make.height.mas_equalTo(48);
make.bottom.equalTo(card).offset(-40 - off_y);
}];
}
#pragma mark - Public
- (void)setDestinationText:(NSString *)destinationText {
_destinationText = destinationText;
self.searchField.text = destinationText;
}
#pragma mark - Actions
- (void)_onCalRouteTapped {
if ([self.delegate respondsToSelector:@selector(bottomBarViewDidTapCalRoute:)]) {
[self.delegate bottomBarViewDidTapCalRoute:self];
}
}
#pragma mark - UITextFieldDelegate
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
//
if ([self.delegate respondsToSelector:@selector(bottomBarViewDidTapSearchField:)]) {
[self.delegate bottomBarViewDidTapSearchField:self];
}
return NO;
}
@end

View File

@@ -0,0 +1,21 @@
//
// ACustomStepView.h
// AMapNavIOSSDK
//
// Created by admin on 2026/3/11.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface ACustomStepView : UIView
@property (nonatomic, readonly , assign) CGFloat value; // 当前值
- (instancetype)initWithValue:(CGFloat)currentValue maxValue:(CGFloat)maxValue min:(CGFloat)minValue;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,121 @@
//
// ACustomStepView.m
// AMapNavIOSSDK
//
// Created by admin on 2026/3/11.
//
#import "ACustomStepView.h"
#import <Masonry/Masonry.h>
#define kStepValue 0.5
@interface ACustomStepView ()
@property CGFloat value;
@property CGFloat maxValue;
@property CGFloat minValue;
@end
@implementation ACustomStepView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.backgroundColor = [UIColor whiteColor];
self.layer.cornerRadius = 4;
self.layer.masksToBounds = YES;
self.clipsToBounds = YES;
self.layer.borderColor = [UIColor colorWithRed:225/255.0 green:225/255.0 blue:225/255.0 alpha:1].CGColor;
self.layer.borderWidth = 1;
[self setupSubviews];
self.value = 0; //
}
return self;
}
- (instancetype)initWithValue:(CGFloat)currentValue maxValue:(CGFloat)maxValue min:(CGFloat)minValue {
// self = [super initWithFrame:CGRectZero];
if (self) {
_value = currentValue;
_maxValue = maxValue;
_minValue = minValue;
}
return self;
}
- (void)setupSubviews {
//
UIButton *minusButton = [UIButton buttonWithType:UIButtonTypeSystem];
[minusButton setTitle:@"-" forState:UIControlStateNormal];
minusButton.titleLabel.font = [UIFont boldSystemFontOfSize:20];
[minusButton addTarget:self action:@selector(decrement:) forControlEvents:UIControlEventTouchUpInside];
[minusButton setTintColor:[UIColor colorWithRed:0x35/255.0 green:0x35/255.0 blue:0x35/255.0 alpha:1]];
[self addSubview:minusButton];
//
UIButton *plusButton = [UIButton buttonWithType:UIButtonTypeSystem];
[plusButton setTitle:@"+" forState:UIControlStateNormal];
plusButton.titleLabel.font = [UIFont boldSystemFontOfSize:20];
[plusButton setTintColor:[UIColor colorWithRed:0x35/255.0 green:0x35/255.0 blue:0x35/255.0 alpha:1]];
[plusButton addTarget:self action:@selector(increment:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:plusButton];
[plusButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.top.right.equalTo(self);
make.height.equalTo(@40);
}];
UIView * line = [[UIView alloc] init];
line.backgroundColor = [UIColor colorWithRed:230/255.0 green:230/255.0 blue:230/255.0 alpha:1];
[self addSubview:line];
[line mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self);
make.top.equalTo(plusButton.mas_bottom);
make.height.equalTo(@1);
}];
[minusButton mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.equalTo(self);
make.top.equalTo(plusButton.mas_bottom);
make.height.equalTo(plusButton);
}];
}
// 1
- (void)decrement:(UIButton *)sender {
if (self.value <= self.minValue) {
return;
}
if (self.value - kStepValue < self.minValue) {
self.value = self.minValue;
return;
}
self.value = self.value - kStepValue;
}
// 1
- (void)increment:(UIButton *)sender {
if (self.value >= self.maxValue) {
return;
}
if (self.value + kStepValue > self.maxValue) {
self.value = self.maxValue;
return;
}
self.value = self.value + kStepValue;
}
@end

View File

@@ -35,6 +35,8 @@ target 'Runner' do
use_frameworks! :linkage => :static
pod 'AMapNavIOSSDK' , :path => './AMapNavIOSSDK'
## 本地仓库
# pod 'AMapNavIOSSDK' , :path => '../../../../demo/ANavDemo'
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))

View File

@@ -17,6 +17,7 @@ PODS:
- AMapNavi-NO-IDFA
- AMapSearch-NO-IDFA
- Masonry
- MBProgressHUD
- MJExtension
- AMapSearch-NO-IDFA (9.7.4):
- AMapFoundation-NO-IDFA (>= 1.8.0)
@@ -42,6 +43,7 @@ PODS:
- image_picker_ios (0.0.1):
- Flutter
- Masonry (1.1.0)
- MBProgressHUD (1.2.0)
- MJExtension (3.4.2)
- mobile_scanner (7.0.0):
- Flutter
@@ -49,9 +51,6 @@ PODS:
- OrderedSet (6.0.3)
- package_info_plus (0.4.5):
- Flutter
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- permission_handler_apple (9.3.0):
- Flutter
- shared_preferences_foundation (0.0.1):
@@ -73,7 +72,6 @@ DEPENDENCIES:
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- mobile_scanner (from `.symlinks/plugins/mobile_scanner/darwin`)
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
@@ -90,6 +88,7 @@ SPEC REPOS:
- AMapNavi-NO-IDFA
- AMapSearch-NO-IDFA
- Masonry
- MBProgressHUD
- MJExtension
- OrderedSet
@@ -118,8 +117,6 @@ EXTERNAL SOURCES:
:path: ".symlinks/plugins/mobile_scanner/darwin"
package_info_plus:
:path: ".symlinks/plugins/package_info_plus/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/darwin"
permission_handler_apple:
:path: ".symlinks/plugins/permission_handler_apple/ios"
shared_preferences_foundation:
@@ -131,30 +128,30 @@ SPEC CHECKSUMS:
AlicloudELS: fbf821383330465a5af84a033f36f263ae46ca41
AlicloudPush: 52cbf38ffc20c07f039cbc72d5738745fd986215
AlicloudUTDID: 5d2f22d50e11eecd38f30bc7a48c71925ea90976
aliyun_push_flutter: 0fc2f048a08687ef256c0cfdd72dd7a550ef3347
aliyun_push_flutter: ab0bf7112ef3797f506770a7a9f47f004635a9f6
AMapFoundation-NO-IDFA: 6ce0ef596d4eb8d934ff498e56747b6de1247b05
AMapLocation-NO-IDFA: 590fd42af0c8ea9eac26978348221bbc16be4ef9
AMapNavi-NO-IDFA: 22edfa7d6a81d75c91756e31b6c26b7746152233
AMapNavIOSSDK: ca325c9ac3378daea6a6be4bd8c34fe48d3ac896
AMapNavIOSSDK: 092382d55290f43b282ffcc522c274996794e2bc
AMapSearch-NO-IDFA: 53b2193244be8f07f3be0a4d5161200236960587
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
device_info_plus: 71ffc6ab7634ade6267c7a93088ed7e4f74e5896
connectivity_plus: 2a701ffec2c0ae28a48cf7540e279787e77c447d
device_info_plus: 97af1d7e84681a90d0693e63169a5d50e0839a0d
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
flutter_pdfview: 32bf27bda6fd85b9dd2c09628a824df5081246cf
geolocator_apple: ab36aa0e8b7d7a2d7639b3b4e48308394e8cef5e
image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326
flutter_inappwebview_ios: 6f63631e2c62a7c350263b13fa5427aedefe81d4
flutter_native_splash: df59bb2e1421aa0282cb2e95618af4dcb0c56c29
flutter_pdfview: 2e4d13ffb774858562ffbdfdb61b40744b191adc
geolocator_apple: 66b711889fd333205763b83c9dcf0a57a28c7afd
image_picker_ios: 4f2f91b01abdb52842a8e277617df877e40f905b
Masonry: 678fab65091a9290e40e2832a55e7ab731aad201
MBProgressHUD: 3ee5efcc380f6a79a7cc9b363dd669c5e1ae7406
MJExtension: e97d164cb411aa9795cf576093a1fa208b4a8dd8
mobile_scanner: 9157936403f5a0644ca3779a38ff8404c5434a93
mobile_scanner: 77265f3dc8d580810e91849d4a0811a90467ed5e
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
package_info_plus: c0502532a26c7662a62a356cebe2692ec5fe4ec4
permission_handler_apple: 9878588469a2b0d0fc1e048d9f43605f92e6cec2
shared_preferences_foundation: 5086985c1d43c5ba4d5e69a4e8083a389e2909e6
url_launcher_ios: bb13df5870e8c4234ca12609d04010a21be43dfa
PODFILE CHECKSUM: 97188da9dab9d4b3372eb4c16e872fbd555fdbea
PODFILE CHECKSUM: b4931d4490f04261e0fda802d44e275ab3619244
COCOAPODS: 1.16.2

View File

@@ -357,14 +357,10 @@
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
);
inputPaths = (
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";

View File

@@ -24,6 +24,7 @@ class TokenInterceptor extends Interceptor {
if (!options.headers.containsKey(tokenKey)) {
// 使用我们自定义的 key 添加 token
options.headers[tokenKey] = token;
print("head.token: $token");
}
}

File diff suppressed because it is too large Load Diff