这东西实现起来并不是很难,就是相对来说啰嗦一点,好了废话不多说 直接上效果
具体效果可以参考京东选取地址的效果哦,由于我不经常发表简书,就直接上图片了,没搞gif。
代码思路:
1.视图结构:标题scrollview+内容scrollview(n个tableview展示数据)
2.主要逻辑:上下scrollview的联动,点击新数据时生产tableview(有时会重用)+titleLabel,内容偏移的处理
哦了,下面直接上代码了,不瞎bb,如果有任何bug和优化的可以@我哦,多谢了,喜欢的话可以点点赞哦
//
// SelectAddressView.h
//
// Created by yaoguanglin on 2017/4/14.
//
#import <UIKit/UIKit.h>
@interface SelectAddressView : UIView
-(instancetype)init:(NSDictionary *)inPutInfoDic outPutInfoBlock:(void(^)(NSDictionary *infoDic))outPutInfoBlock;
@end
//
// SelectAddressView.m
//
// Created by yaoguanglin on 2017/4/14.
//
#import "SelectAddressView.h"
#import "DigMachineFinanceMacro.h"
#import "CAttention.h"
#import "Masonry.h"
@interface SelectAddressView ()<UITableViewDelegate,UITableViewDataSource>
@property(nonatomic,strong)void(^outPutInfoBlock)(NSDictionary *infoDic);
@property(nonatomic,strong)UIScrollView *selectAddressScrollView;
@property(nonatomic,strong)UIScrollView *titlesScrollView;
@property(nonatomic,strong)UIView *moveLineView;
@property(nonatomic,strong)NSMutableDictionary *headTitleMDic;
@property(nonatomic,assign)NSInteger startTag;
@property(nonatomic,strong)NSMutableDictionary *selectIndexPathMDic;
@property(nonatomic,strong)NSMutableDictionary *addressDataMDic;
@end
@implementation SelectAddressView
-(NSMutableDictionary *)headTitleMDic {
if(!_headTitleMDic) {
_headTitleMDic=[NSMutableDictionary dictionary];
}
return _headTitleMDic;
}
-(NSMutableDictionary *)addressDataMDic {
if(!_addressDataMDic) {
_addressDataMDic=[NSMutableDictionary dictionary];
}
return _addressDataMDic;
}
-(NSMutableDictionary *)selectIndexPathMDic {
if(!_selectIndexPathMDic) {
_selectIndexPathMDic=[NSMutableDictionary dictionary];
}
return _selectIndexPathMDic;
}
-(UIView *)moveLineView {
if(!_moveLineView) {
_moveLineView=[[UIView alloc]initWithFrame:CGRectZero];
_moveLineView.backgroundColor=[UIColor redColor];
}
return _moveLineView;
}
-(UIScrollView *)titlesScrollView {
if(!_titlesScrollView) {
_titlesScrollView=[[UIScrollView alloc]initWithFrame:CGRectMake(0, 30, SCREEN_WIDTH, 60-30)];
_titlesScrollView.showsHorizontalScrollIndicator=NO;
_titlesScrollView.showsVerticalScrollIndicator=NO;
_titlesScrollView.backgroundColor=[UIColor clearColor];
_titlesScrollView.contentSize=CGSizeMake(0, 60-30);
}
return _titlesScrollView;
}
-(UIScrollView *)selectAddressScrollView {
if(!_selectAddressScrollView) {
_selectAddressScrollView=[[UIScrollView alloc]initWithFrame:CGRectMake(0, 60, SCREEN_WIDTH, self.frame.size.height-60)];
_selectAddressScrollView.pagingEnabled=YES;
_selectAddressScrollView.showsHorizontalScrollIndicator=NO;
_selectAddressScrollView.showsVerticalScrollIndicator=NO;
_selectAddressScrollView.delegate=self;
_selectAddressScrollView.tag=500;
}
return _selectAddressScrollView;
}
-(UILabel *)titleLabel:(NSInteger)tag text:(NSString *)text{
UILabel *label=[[UILabel alloc]init];
label.textColor=[UIColor redColor];
label.tag=tag;
label.preferredMaxLayoutWidth=SCREEN_WIDTH/3;
label.text=text;
label.font=[UIFont systemFontOfSize:13];
label.textAlignment=NSTextAlignmentCenter;
label.userInteractionEnabled=YES;
[label addGestureRecognizer:[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(titleLabelAction:)]];
return label;
}
-(UITableView *)selectAddressTableView:(CGRect)frame tag:(NSInteger)tag {
UITableView *selectAddressTableView=[[UITableView alloc]initWithFrame:frame style:UITableViewStylePlain];
selectAddressTableView.separatorStyle=UITableViewCellSeparatorStyleNone;
selectAddressTableView.tag=tag;
selectAddressTableView.delegate=self;
selectAddressTableView.dataSource=self;
[selectAddressTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:[NSString stringWithFormat:@"selectAddressTableViewCellReuseID%zd",tag]];
return selectAddressTableView;
}
-(instancetype)init:(NSDictionary *)inPutInfoDic outPutInfoBlock:(void(^)(NSDictionary *infoDic))outPutInfoBlock{
if(self=[super initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT-300)]) {
self.backgroundColor=[UIColor whiteColor];
self.outPutInfoBlock=outPutInfoBlock;
self.startTag=300;
[self addHeaderView];
[self addSubview:self.selectAddressScrollView];
[self firstAddTableViews];
}
return self;
}
- (void)addHeaderView {
UIView *headerView=[[UIView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH,60)];
[self addSubview:headerView];
headerView.backgroundColor=[UIColor whiteColor];
UILabel *titleLabel=[[UILabel alloc]init];
titleLabel.textColor=HEXVALEUCOLOR(0x666666, 1.0);
titleLabel.text=@"所在地区";
titleLabel.font=[UIFont systemFontOfSize:15];
[headerView addSubview:titleLabel];
[titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_offset(5);
make.centerX.mas_equalTo(headerView);
}];
[headerView addSubview:self.titlesScrollView];
UIView *lineView=[[UIView alloc]init];
lineView.backgroundColor=HEXVALEUCOLOR(0xcccccc, 1.0);
[headerView addSubview:lineView];
[lineView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_offset(0);
make.bottom.mas_offset(0);
make.right.mas_offset(0);
make.height.mas_equalTo(0.5);
}];
}
//首次创建时增加tableview
- (void)firstAddTableViews {
[self requestData:nil tableViewTag:self.startTag];
}
//刷新tableview和标题栏
- (void)refreshSubviews:(NSInteger)tag infoAry:(NSArray*)infoAry{
for(NSInteger i=(tag-self.startTag);i<(self.selectAddressScrollView.contentSize.width/SCREEN_WIDTH);i++) {
UITableView *tableView=[self.selectAddressScrollView viewWithTag:(self.startTag+i)];
[self.addressDataMDic removeObjectForKey:@(self.startTag+i)];
[self removeHeadTitleLabel:@(self.startTag+i)];
[self.selectIndexPathMDic removeObjectForKey:@(self.startTag+i)];
[tableView reloadData];
}
[self setHeadTitleLabel:@(tag) value:@"请选择"];
[self.addressDataMDic setObject:infoAry forKey:@(tag)];
self.selectAddressScrollView.contentSize=CGSizeMake(SCREEN_WIDTH*(tag-self.startTag+1), self.selectAddressScrollView.frame.size.height);
if([self.selectAddressScrollView viewWithTag:tag]) {
UITableView *tableView=[self.selectAddressScrollView viewWithTag:tag];
[tableView reloadData];
}else {
[self.selectAddressScrollView addSubview:[self selectAddressTableView:CGRectMake(SCREEN_WIDTH*(tag-self.startTag), 0, SCREEN_WIDTH, self.selectAddressScrollView.frame.size.height) tag:tag]];
}
[self.selectAddressScrollView setContentOffset:CGPointMake(SCREEN_WIDTH*(tag-self.startTag), 0) animated:YES];
}
- (void)removeHeadTitleLabel:(id)key {
[self.headTitleMDic removeObjectForKey:key];
UILabel *titleLabel=[self.titlesScrollView viewWithTag:[key integerValue]];
self.titlesScrollView.contentSize=CGSizeMake(self.titlesScrollView.contentSize.width-titleLabel.frame.size.width, self.titlesScrollView.contentSize.height);
[titleLabel removeFromSuperview];
}
- (void)setHeadTitleLabel:(id)key value:(NSString *)value{
if([self.headTitleMDic.allKeys containsObject:key]) { //修改
[self.headTitleMDic setObject:value forKey:key];
UILabel *titleLabel=[self.titlesScrollView viewWithTag:[key integerValue]];
titleLabel.text=value;
titleLabel.textColor=HEXVALEUCOLOR(0x666666, 1.0);
self.titlesScrollView.contentSize=CGSizeMake(self.titlesScrollView.contentSize.width-titleLabel.frame.size.width, self.titlesScrollView.contentSize.height);
titleLabel.frame=CGRectMake(titleLabel.frame.origin.x, 0, titleLabel.intrinsicContentSize.width+20, self.titlesScrollView.contentSize.height);
self.titlesScrollView.contentSize=CGSizeMake(self.titlesScrollView.contentSize.width+titleLabel.intrinsicContentSize.width+20, self.titlesScrollView.contentSize.height);
[self.titlesScrollView addSubview:titleLabel];
[self.titlesScrollView addSubview:self.moveLineView];
self.moveLineView.frame=CGRectMake(titleLabel.frame.origin.x+10, self.titlesScrollView.frame.size.height-2, titleLabel.intrinsicContentSize.width, 2);
[self moveTitleScrollView:titleLabel.frame];
}else { //增加
[self.headTitleMDic setObject:value forKey:key];
UILabel *titleLabel=[self titleLabel:[key integerValue] text:value];
titleLabel.frame=CGRectMake(self.titlesScrollView.contentSize.width, 0, titleLabel.intrinsicContentSize.width+20, self.titlesScrollView.contentSize.height);
self.titlesScrollView.contentSize=CGSizeMake(self.titlesScrollView.contentSize.width+titleLabel.intrinsicContentSize.width+20, self.titlesScrollView.contentSize.height);
[self.titlesScrollView addSubview:titleLabel];
[self.titlesScrollView addSubview:self.moveLineView];
[UIView animateWithDuration:.25 animations:^{
self.moveLineView.frame=CGRectMake(titleLabel.frame.origin.x+10, self.titlesScrollView.frame.size.height-2, titleLabel.intrinsicContentSize.width, 2);
}];
[self moveTitleScrollView:titleLabel.frame];
}
}
#pragma mark - UITableViewDelegate,UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSArray *ary = self.addressDataMDic[@(tableView.tag)];
return ary.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[NSString stringWithFormat:@"selectAddressTableViewCellReuseID%zd",tableView.tag] forIndexPath:indexPath];
cell.selectionStyle=UITableViewCellSelectionStyleNone;
cell.textLabel.textColor=HEXVALEUCOLOR(0x454545, 1.0);
cell.textLabel.font=[UIFont systemFontOfSize:14];
if(self.selectIndexPathMDic[@(tableView.tag)]) {
NSIndexPath *selectIndexPath=self.selectIndexPathMDic[@(tableView.tag)];
if(indexPath.row==selectIndexPath.row) {
cell.textLabel.textColor=[UIColor redColor];
}
}
NSArray *ary = self.addressDataMDic[@(tableView.tag)];
cell.textLabel.text=ary[indexPath.row][@"AREANAME"];
return cell;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSIndexPath *selectIndexPath=self.selectIndexPathMDic[@(tableView.tag)];
//点击未点击过的cell刷新数据
if(!selectIndexPath||(selectIndexPath.row!=indexPath.row)) {
NSArray *ary = self.addressDataMDic[@(tableView.tag)];
[self setHeadTitleLabel:@(tableView.tag) value:ary[indexPath.row][@"AREANAME"]];
[self.selectIndexPathMDic setObject:indexPath forKey:@(tableView.tag)];
[tableView reloadData];
[self requestData:nil tableViewTag:(tableView.tag+1)];
return;
}
//点击点击过的cell不用刷新数据
[self.selectAddressScrollView setContentOffset:CGPointMake(SCREEN_WIDTH*(tableView.tag-self.startTag+1), 0) animated:YES];
UILabel *titleLabel=[self.titlesScrollView viewWithTag:(tableView.tag+1)];
[UIView animateWithDuration:.25 animations:^{
self.moveLineView.frame=CGRectMake(titleLabel.frame.origin.x+10, self.titlesScrollView.frame.size.height-2, titleLabel.intrinsicContentSize.width, 2);
}];
[self moveTitleScrollView:titleLabel.frame];
}
#pragma mark - scrollViewDelegate
-(void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset {
if(500==scrollView.tag) {
UILabel *titleLabel=[self.titlesScrollView viewWithTag:((targetContentOffset->x)/SCREEN_WIDTH+self.startTag)];
[self moveTitleScrollView:titleLabel.frame];
[UIView animateWithDuration:.25 animations:^{
self.moveLineView.frame=CGRectMake(titleLabel.frame.origin.x+10, self.titlesScrollView.frame.size.height-2, titleLabel.intrinsicContentSize.width, 2);
}];
}
}
//处理标题视图滚动到可见
- (void)moveTitleScrollView:(CGRect)titleLabelFrame {
if(CGRectGetMaxX(titleLabelFrame)>(self.titlesScrollView.contentOffset.x+SCREEN_WIDTH)) {
[self.titlesScrollView setContentOffset:CGPointMake(CGRectGetMaxX(titleLabelFrame)-SCREEN_WIDTH, 0) animated:YES];
return;
}else if(CGRectGetMinX(titleLabelFrame)<self.titlesScrollView.contentOffset.x) {
[self.titlesScrollView setContentOffset:CGPointMake(CGRectGetMinX(titleLabelFrame), 0) animated:YES];
}
}
#pragma mark -Action
- (void)titleLabelAction:(UITapGestureRecognizer*)tap {
UILabel *titleLabel=(UILabel *)tap.view;
[UIView animateWithDuration:.25 animations:^{
self.moveLineView.frame=CGRectMake(titleLabel.frame.origin.x+10, self.titlesScrollView.frame.size.height-2, titleLabel.intrinsicContentSize.width, 2);
}];
[self.selectAddressScrollView setContentOffset:CGPointMake(SCREEN_WIDTH*(titleLabel.tag-self.startTag), 0) animated:YES];
}
#pragma mark - 请求数据
- (void)requestData:(NSDictionary *)paramDic tableViewTag:(NSInteger)tag{
[self refreshSubviews:tag infoAry:@[
@{
@"AREACODE": @"110100",
@"AREANAME": @"北京市XX"
},
@{
@"AREACODE": @"120100",
@"AREANAME": @"上"
},
@{
@"AREACODE": @"130100",
@"AREANAME": @"南京市ff"
}]];
}
@end