iOS小技能: 地址选择器(支持省份,省市,省市区三种联动)

546 阅读5分钟

“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 6 天,点击查看活动详情

前言

  • 效果图

在这里插入图片描述

I 实现

1.1 加载数据

先请求接口获取数据。如果获取失败,就先从本地文件address_CRM获取数据


-(instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {//
        
        self.provinces = [QCTAreaListTool shareQCTAreaListTool].AreaList4CRM;// 先请求接口获取数据。如果获取失败,就先从本地文件address_CRM获取数据
        
        _nameStr = @"areaName";
        _cityStr = @"childNode";
        
                if (self.provinces.count == 0) {
                    
                    
                    
                    
                    NSString *addressPath = [[NSBundle mainBundle] pathForResource:@"address_CRM" ofType:@"plist"];
                    self.provinces = [[NSArray alloc]initWithContentsOfFile:addressPath];
                    
                    
        //            self.provinces = dict[@"address"];
        //            _nameStr = @"name";
        //            _cityStr = @"sub";
                    
                    
                    
                }
//
        
        
        
        
        
        
        self.provinceSelectIndex = -1;
        self.citySelectIndex = -1;
        self.areaSelectIndex = -1;
        [self setupChildViews];
    }
    return self;
}

1.2 使用方法

  • h
/**
 类方法加载地址选择器
 
 @param height 传入选择器高度(默认300)
 @param pickOver 传入选择完成的回调
 @param pickCancel 传入取消输入的回调
 
 @param yesOrNo 是否选择城市z之后直接执行完成回调
 
 
 @return 返回地址选择器
 */


+(instancetype *) addressPickerWithRect:(CGRect)Rect yesOrNo:(NSString *)str PickOver:(void(^)(NSDictionary * addressDict))pickOver PickCancel:(void(^)(void))pickCancel;

/**
 
 开户城市 默认为开户城市
 */
@property (nonatomic, copy) NSString * titleStr;


  • 实例化
- (LGAddressPicker *)AddressPicker{
    
    __weak __typeof__(self) weakSelf = self;

    
    if (!_AddressPicker) {
        
        
        
        
        _AddressPicker = [LGAddressPicker addressPickerWithRect:CGRectMake(0, kHeight - KWratio(430), kWidth, KWratio(430)) yesOrNo:@"no" PickOver:^(NSDictionary *addressDict) {
            
            
            
            
            NSLog(@"地区选择完毕!");
            
            
            
            
            
            
            weakSelf.viewModel.AddressPickerModel.area = addressDict[@"area"];
            weakSelf.viewModel.AddressPickerModel.areaId = addressDict[@"areaID"];
            
            
            weakSelf.viewModel.AddressPickerModel.city = addressDict[@"city"];
            
            
            
            
            weakSelf.viewModel.AddressPickerModel.cityId = addressDict[@"cityID"];
            

            weakSelf.viewModel.AddressPickerModel.province = addressDict[@"province"];

            weakSelf.viewModel.AddressPickerModel.provinceId = addressDict[@"provinceID"];
            
            
            
            
            
            
            
            NSString* Title =         [NSString stringWithFormat:@"%@%@%@",weakSelf.viewModel.AddressPickerModel.province,weakSelf.viewModel.AddressPickerModel.city,weakSelf.viewModel.AddressPickerModel.area] ;
            
            weakSelf.viewModel.ProductplaceModel.content = Title ;
            
            
            
            [self.viewModel.reloadProductPlaceModelSubject sendNext:nil];
            
                     
            [weakSelf.modal hide:YES];

//
//
        } PickCancel:^{
            
            
//            NSLog(@"您已取消选择地区!");
            
            [weakSelf.modal hide:YES];

            
        }];
        
        _AddressPicker.titleStr = @"城市";
        
        

        
    }
    
    

    
    
    return  _AddressPicker;
    
    
}


II 完整的代码


#import "LGAddressPicker.h"
#import "QCTAreaListTool.h"

#define ScreenSize [UIScreen mainScreen].bounds.size
#define GetWidth(view) [self getViewWidth:view]
#define SetWidth(view,width) [self setViewWidth:view Width:width]
#define GetTextWidth(text) [self getWidthWithText:text]
#define TinyColor HWColor(255, 54, 87)

@interface LGAddressPicker()<UITableViewDataSource, UITableViewDelegate>
/**
 子视图
 */
@property (nonatomic, strong) UIButton * provinceButton;
@property (nonatomic, strong) UIButton * cityButton;
@property (nonatomic, strong) UIButton * areaButton;
@property (nonatomic,strong) UITableView *provinceTabView;
@property (nonatomic,strong) UITableView *cityTabView;
@property (nonatomic,strong) UITableView *areaTabView;
@property (nonatomic,strong) UIScrollView *scroView;
@property (nonatomic,strong) UIView *indicator;
/**
 标题,例如:选择开户城市
 */
@property (nonatomic,strong) UILabel *titleLabel;



/**
 变量
 */
@property (nonatomic, strong) void(^pickOver)(id content);
@property (nonatomic, strong) void(^pickCancel)(void);
@property (nonatomic, strong) NSArray * provinces;
@property (nonatomic, strong) NSArray * cities;
@property (nonatomic, strong) NSArray * areas;
@property (nonatomic, assign) NSInteger provinceSelectIndex;
@property (nonatomic, assign) NSInteger citySelectIndex;
@property (nonatomic, assign) NSInteger areaSelectIndex;
@property (nonatomic, assign) NSString *nameStr;
@property (nonatomic, assign) NSString *cityStr;
@property (nonatomic, strong) NSString *yesOrNo;

@end

@implementation LGAddressPicker

#pragma mark - 类方法
/**
 类方法加载地址选择器
 
 @param height 传入选择器高度(默认300)
 @param pickOver 传入选择完成的回调
 @param pickCancel 传入取消输入的回调
 @return 返回地址选择器
 */
+(LGAddressPicker *) addressPickerWithRect:(CGRect)Rect yesOrNo:(NSString *)str PickOver:(void(^)(NSDictionary * addressDict))pickOver PickCancel:(void(^)(void))pickCancel
{
    LGAddressPicker * picker = [[LGAddressPicker alloc] initWithFrame:Rect];
    picker.pickOver = pickOver;
    picker.pickCancel = pickCancel;
    picker.yesOrNo = str;
    return picker;
}

-(instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {//
        
        self.provinces = [QCTAreaListTool shareQCTAreaListTool].AreaList4CRM;// 先请求接口获取数据。如果获取失败,就先从本地文件address_CRM获取数据
        
        _nameStr = @"areaName";
        _cityStr = @"childNode";
        
                if (self.provinces.count == 0) {
                    
                    
                    
                    
                    NSString *addressPath = [[NSBundle mainBundle] pathForResource:@"address_CRM" ofType:@"plist"];
                    self.provinces = [[NSArray alloc]initWithContentsOfFile:addressPath];
                    
                    
        //            self.provinces = dict[@"address"];
        //            _nameStr = @"name";
        //            _cityStr = @"sub";
                    
                    
                    
                }
//
        
        
        
        
        
        
        self.provinceSelectIndex = -1;
        self.citySelectIndex = -1;
        self.areaSelectIndex = -1;
        [self setupChildViews];
    }
    return self;
}




#pragma mark - 事件监听
/**
 点击关闭按钮
 */
-(void) closeButtonClick
{
    if (self.pickCancel) self.pickCancel();
}

/**
 点击省份按钮
 */
-(void) provinceButtonClick
{
    self.citySelectIndex = -1;
    self.areaSelectIndex = -1;
    
    [UIView animateWithDuration:0.5 animations:^{
        self.scroView.contentOffset = CGPointMake(0, 0);
        self.indicator.transform = CGAffineTransformIdentity;
        SetWidth(self.indicator, GetWidth(self.provinceButton));
        
        self.cityButton.transform = CGAffineTransformIdentity;
        self.cityButton.alpha = 0;
        self.areaButton.transform = CGAffineTransformIdentity;
        self.areaButton.alpha = 0;
    }];
}

/**
 点击城市按钮
 */
-(void) cityButtonClick
{
    self.areaSelectIndex = -1;
    
    [UIView animateWithDuration:0.5 animations:^{
        self.scroView.contentOffset = CGPointMake(ScreenSize.width, 0);
        self.indicator.transform = CGAffineTransformMakeTranslation(self.provinceButton.frame.size.width, 0);
        SetWidth(self.indicator, GetWidth(self.cityButton));
        
        self.areaButton.transform = CGAffineTransformIdentity;
        self.areaButton.alpha = 0;
    }];
}

/**
 点击区域按钮
 */
-(void) areaButtonClick
{
    [UIView animateWithDuration:0.5 animations:^{
        self.indicator.transform = CGAffineTransformMakeTranslation(CGRectGetMaxX(self.cityButton.frame), 0);
        SetWidth(self.indicator, GetWidth(self.areaButton));
        
        self.scroView.contentOffset = CGPointMake(ScreenSize.width * 2, 0);
    }];
}

#pragma mark - 数据源
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (tableView == self.provinceTabView)
    {
        return self.provinces.count;
    }
    else if (tableView == self.cityTabView)
    {
        return self.cities.count;
    }
    else
    {
        return self.areas.count;
    }
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString * cellID = @"addressCell";
    UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    
    if (cell == nil)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
    }
    
    if (tableView == self.provinceTabView)
    {
        cell.textLabel.text = self.provinces[indexPath.row][_nameStr];
        if (indexPath.row == self.provinceSelectIndex)
        {
            cell.textLabel.textColor = TinyColor;
        }
        else
        {
            cell.textLabel.textColor = [UIColor blackColor];
        }
    }
    else if (tableView == self.cityTabView)
    {
        cell.textLabel.text = self.cities[indexPath.row][_nameStr];
        if (indexPath.row == self.citySelectIndex)
        {
            cell.textLabel.textColor = TinyColor;
        }
        else
        {
            cell.textLabel.textColor = [UIColor blackColor];
        }
    }
    else
    {
        if ([_cityStr isEqualToString:@"sub"]) {
            cell.textLabel.text = self.areas[indexPath.row];
        } else {
            cell.textLabel.text = self.areas[indexPath.row][_nameStr];
        }
        if (indexPath.row == self.areaSelectIndex)
        {
            cell.textLabel.textColor = TinyColor;
        }
        else
        {
            cell.textLabel.textColor = [UIColor blackColor];
        }
    }
    
    cell.textLabel.font = [UIFont systemFontOfSize:displayFontSize(13.0f)];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    
    return cell;
}


#pragma mark - 代理
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (tableView == self.provinceTabView)
    {
        self.provinceSelectIndex = indexPath.row;
        [self.provinceTabView reloadData];
        [self.provinceButton setTitle:self.provinces[indexPath.row][_nameStr] forState:UIControlStateNormal];
        SetWidth(self.provinceButton, GetTextWidth(self.provinceButton.titleLabel.text));
        
        self.cities = self.provinces[indexPath.row][_cityStr];
        [self.cityTabView reloadData];
        
        [self.cityButton setTitle:@"请选择" forState:UIControlStateNormal];
        [self.cityButton setTitleColor:BASE_RED_COLOR forState:UIControlStateNormal];
        [self.provinceButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        
        SetWidth(self.cityButton, GetTextWidth(self.cityButton.titleLabel.text));
        SetWidth(self.indicator,GetWidth(self.cityButton));
        
        [UIView animateWithDuration:0.5 animations:^{
            self.cityButton.alpha = 1;
            self.cityButton.transform = CGAffineTransformMakeTranslation(GetWidth(self.provinceButton), 0);
            self.indicator.transform = CGAffineTransformMakeTranslation(GetWidth(self.provinceButton), 0);
            self.scroView.contentOffset = CGPointMake(ScreenSize.width, 0);
        }];
    }
    else if (tableView == self.cityTabView)
    {
        self.citySelectIndex = indexPath.row;
        [self.cityTabView reloadData];
        
        [self.cityButton setTitle:self.cities[indexPath.row][_nameStr] forState:UIControlStateNormal];
        SetWidth(self.cityButton, GetTextWidth(self.cityButton.titleLabel.text));
        
        self.areas = self.cities[indexPath.row][_cityStr];
        [self.areaTabView reloadData];
        
        if ([_yesOrNo isEqualToString:@"yes"]) {
            if (self.pickOver)
            {
                NSString * province = self.provinces[self.provinceSelectIndex][_nameStr];
                NSString * city = self.cities[indexPath.row][_nameStr];
                
                
                NSString * provinceID = self.provinces[self.provinceSelectIndex][@"areaId"];
                NSString * cityID = self.cities[indexPath.row][@"areaId"];
                
                NSDictionary * dict = @{@"province":province, @"city":city, @"area":@"", @"provinceID":provinceID, @"cityID":cityID, @"areaID":@""};
                self.pickOver(dict);
            }
            return;

        }
        
        if (self.areas.count <= 0)
        {
            if (self.pickOver)
            {
                NSString * province = self.provinces[self.provinceSelectIndex][_nameStr];
                NSString * city = self.cities[indexPath.row][_nameStr];
                
                
                NSString * provinceID = self.provinces[self.provinceSelectIndex][@"areaId"];
                NSString * cityID = self.cities[indexPath.row][@"areaId"];

                NSDictionary * dict = @{@"province":province, @"city":city, @"area":@"", @"provinceID":provinceID, @"cityID":cityID, @"areaID":@""};
                self.pickOver(dict);
            }
            return;
        }
        
        [self.areaButton setTitle:@"请选择" forState:UIControlStateNormal];
        [self.areaButton setTitleColor:BASE_RED_COLOR forState:UIControlStateNormal];
        [self.cityButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [self.provinceButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        
        SetWidth(self.areaButton, GetTextWidth(self.areaButton.titleLabel.text));
        
        SetWidth(self.indicator,GetWidth(self.areaButton));
        
        [UIView animateWithDuration:0.5 animations:^{
            self.areaButton.alpha = 1;
            self.areaButton.transform = CGAffineTransformMakeTranslation(GetWidth(self.provinceButton)+GetWidth(self.cityButton), 0);
            self.indicator.transform = CGAffineTransformMakeTranslation(GetWidth(self.provinceButton)+GetWidth(self.cityButton), 0);
            self.scroView.contentOffset = CGPointMake(ScreenSize.width * 2, 0);
        }];
    }
    else
    {
        self.areaSelectIndex = indexPath.row;
        [self.areaTabView reloadData];
        NSString * area = @"";
        NSString * areaID = @"";
        NSString * provinceID = @"";
        NSString * cityID = @"";
        if ([_cityStr isEqualToString:@"sub"]) {
            [self.areaButton setTitle:self.areas[indexPath.row] forState:UIControlStateNormal];
            area = self.areas[indexPath.row];
//            areaID =
        } else {
            [self.areaButton setTitle:self.areas[indexPath.row][_nameStr] forState:UIControlStateNormal];
            area = self.areas[indexPath.row][_nameStr];
            areaID = self.areas[indexPath.row][@"areaId"];
            provinceID = self.provinces[self.provinceSelectIndex][@"areaId"];
            cityID = self.cities[self.citySelectIndex][@"areaId"];

        }
        [self.areaButton setTitleColor:BASE_RED_COLOR forState:UIControlStateNormal];
        [self.provinceButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        
        SetWidth(self.areaButton, GetTextWidth(self.areaButton.titleLabel.text));
        
        //执行Block,传出选中的内容
        NSString * province = self.provinces[self.provinceSelectIndex][_nameStr];
        NSString * city = self.cities[self.citySelectIndex][_nameStr];

        NSDictionary * dict = @{@"province":province, @"city":city, @"area":area , @"provinceID":provinceID, @"cityID":cityID, @"areaID":areaID};
        if (self.pickOver) self.pickOver(dict);
    }
}

- (void)setTitleStr:(NSString *)titleStr{
    
    _titleStr = titleStr;
    
    
    
    self.titleLabel.text = titleStr;
    
}


#pragma mark - 方法抽取
/**
 初始化子视图
 */
- (void)setupChildViews
{
    self.backgroundColor = [UIColor whiteColor];
    
    // 选择器标题
    UILabel * titleLabel = [ControlManager text:@"开户城市" font:displayFontSize(14.0f) color:HWColor(51, 51, 51) alingment:1 fontWithName:@"PingFang-SC-Medium"];
    titleLabel.frame = CGRectMake(0, 0, GetWidth(self), KWratio(50));
    [self addSubview:titleLabel];
    self.titleLabel= titleLabel;
    
    
    
    
    // 关闭按钮
    UIButton * closeButton = [[UIButton alloc] initWithFrame:CGRectMake(kWidth - KWratio(50), 0, KWratio(50), KWratio(50))];
    [closeButton setImage:[UIImage imageNamed:@"icon_xinzengmendian_guanbi"] forState:UIControlStateNormal];
    [closeButton addTarget:self action:@selector(closeButtonClick) forControlEvents:UIControlEventTouchUpInside];
    [self addSubview:closeButton];
    
    // 地址按钮
    for (int i = 0; i < 3; i++)
    {
        UIButton * button = [[UIButton alloc] init];
        [button setTitle:@"请选择" forState:UIControlStateNormal];
        [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        button.titleLabel.font = [UIFont systemFontOfSize:13];
        button.backgroundColor = [UIColor whiteColor];
        button.frame = CGRectMake(0, CGRectGetMaxY(titleLabel.frame),GetTextWidth(button.titleLabel.text), KWratio(44));
        [self addSubview:button];
        switch (i)
        {
            case 0:
                self.areaButton = button;
                self.areaButton.alpha = 0;
                [self.areaButton addTarget:self action:@selector(areaButtonClick) forControlEvents:UIControlEventTouchUpInside];
                break;
            case 1:
                self.cityButton = button;
                self.cityButton.alpha = 0;
                [self.cityButton addTarget:self action:@selector(cityButtonClick) forControlEvents:UIControlEventTouchUpInside];
                break;
            default:
                self.provinceButton = button;
                [self.provinceButton setTitleColor:BASE_RED_COLOR forState:UIControlStateNormal];
                [self.provinceButton addTarget:self action:@selector(provinceButtonClick) forControlEvents:UIControlEventTouchUpInside];
                break;
        }
    }
    
    // 分割线
    UIView * sepLine = [[UIView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(self.provinceButton.frame), ScreenSize.width, 1)];
    sepLine.backgroundColor = [UIColor colorWithRed:0.8 green:0.8 blue:0.8 alpha:0.8];
    [self addSubview:sepLine];
    UIView * sepLine2 = [[UIView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(titleLabel.frame), ScreenSize.width, 1)];
    sepLine2.backgroundColor = [UIColor colorWithRed:0.8 green:0.8 blue:0.8 alpha:0.8];
    [self addSubview:sepLine2];
    
    
    // 指示器
    self.indicator = [[UIView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(self.provinceButton.frame), GetWidth(self.provinceButton), 1)];
    self.indicator.backgroundColor = TinyColor;
    [self addSubview:self.indicator];
    
    // ScroView
    self.scroView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, CGRectGetMaxY(sepLine.frame), ScreenSize.width, self.frame.size.height-CGRectGetMaxY(sepLine.frame))];
    self.scroView.contentSize = CGSizeMake(ScreenSize.width * 3, 0);
    self.scroView.scrollEnabled = NO;
    
    // ScroView中TabView
    for (int i = 0; i < 3; i++)
    {
        UITableView * tabView = [[UITableView alloc] initWithFrame:CGRectMake(i*ScreenSize.width, 0, ScreenSize.width, self.scroView.frame.size.height)];
        tabView.delegate = self;
        tabView.dataSource = self;
        tabView.separatorStyle = UITableViewCellSeparatorStyleNone;
        [self.scroView addSubview:tabView];
        switch (i)
        {
            case 0:
                self.provinceTabView = tabView;
                break;
            case 1:
                self.cityTabView = tabView;
                break;
            default:
                self.areaTabView = tabView;
                break;
        }
    }
    [self addSubview:self.scroView];
}

/**
 获取视图宽度
 
 @param view 传入视图
 @return 返回宽度
 */
-(CGFloat) getViewWidth:(UIView *)view
{
    return view.frame.size.width;
}

/**
 设置视图宽度
 
 @param view 传入视图
 @param width 传入宽度
 */
-(void) setViewWidth:(UIView *)view Width:(CGFloat)width
{
    CGRect frame = view.frame;
    frame.size.width = width;
    view.frame = frame;
}


/**
 根据文字内容获取文字宽度
 
 @param text 传入文字
 @return 返回宽度
 */
-(CGFloat) getWidthWithText:(NSString *)text
{
    UIFont * font = [UIFont systemFontOfSize:13];
    CGSize size = CGSizeMake(MAXFLOAT, 30.f);
    CGSize textSize = [text boundingRectWithSize:size options:NSStringDrawingTruncatesLastVisibleLine|NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:nil].size;
    return textSize.width + 20;
}
@end

see also

iOS AddressPickerView地址选择器,支持省份,省市,省市区,也支持打开显示上一次选择的地址【回调参数包括选中的省(provinceId)、市ID(cityId)区ID(areaid】 blog.csdn.net/z929118967/…