iOS 仿热门话题界面(tableView)
LinHopwood
8年前
<h3><strong>废话不多说直接上代码!</strong></h3> <p style="text-align:center"><img src="https://simg.open-open.com/show/c25ba4d26c9cd354700379f74bf280e5.png"></p> <p>这个功能应该是挺常见的, 一个tableView到另一个tableView, 类似segment的一个东西, 我把它封装起来了:</p> <pre> <code class="language-objectivec">// // ViewController.m // // // Created by 高雅馨 on 16/6/3. // Copyright © 2016年 高雅馨. All rights reserved. // #import "DCNavTabBarController.h" #import "HTMacro.h" @interface DCNavTabBarController ()<UIScrollViewDelegate> @property (nonatomic, weak) UIButton *oldBtn; @property(nonatomic,strong) NSArray *VCArr; @property (nonatomic, weak) UIScrollView *contentView; @property (nonatomic, weak) UIScrollView *topBar; @property(nonatomic,assign) CGFloat btnW ; @property (nonatomic, weak) UIView *slider; @end @implementation DCNavTabBarController -(UIColor *)sliderColor { if(_sliderColor == nil) { _sliderColor = [UIColor colorWithRed:1.00 green:0.36 blue:0.25 alpha:1.00]; } return _sliderColor; } -(UIColor *)btnTextNomalColor { if(_btnTextNomalColor == nil) { _btnTextNomalColor = [UIColor colorWithWhite:0.205 alpha:1.000]; } return _btnTextNomalColor; } -(UIColor *)btnTextSeletedColor { if(_btnTextSeletedColor == nil) { _btnTextSeletedColor = [UIColor colorWithRed:1.00 green:0.36 blue:0.25 alpha:1.00]; } return _btnTextSeletedColor; } -(UIColor *)topBarColor { if(_topBarColor == nil) { _topBarColor = [UIColor whiteColor]; } return _topBarColor; } -(instancetype)initWithSubViewControllers:(NSArray *)subViewControllers { if(self = [super init]) { _VCArr = subViewControllers; } return self; } - (void)viewDidLoad { [super viewDidLoad]; //添加上面的导航条 [self addTopBar]; //添加子控制器 [self addVCView]; //添加滑块 [self addSliderView]; } -(void)addSliderView { if(self.VCArr.count == 0) return; UIView *slider = [[UIView alloc]initWithFrame:CGRectMake(25,41,self.btnW - 50, 3)]; slider.backgroundColor = self.sliderColor; [self.topBar addSubview:slider]; self.slider = slider; } -(void)addTopBar { if(self.VCArr.count == 0) return; NSUInteger count = self.VCArr.count; UIScrollView *scrollView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, 44)]; scrollView.backgroundColor = self.topBarColor; self.topBar = scrollView; self.topBar.bounces = NO; [self.view addSubview:self.topBar]; if(count <= 5) { self.btnW = SCREEN_WIDTH / count; } else { self.btnW = SCREEN_WIDTH / 5.0; } //添加button for (int i = 0; i<count; i++) { UIViewController *vc = self.VCArr[i]; UIButton *btn = [[UIButton alloc]initWithFrame:CGRectMake(i*self.btnW, 0, self.btnW, 44)]; btn.titleLabel.font = [UIFont systemFontOfSize:15]; btn.titleLabel.numberOfLines = 0; btn.titleLabel.textAlignment = 1; btn.tag = 10000+i; [btn setTitleColor:self.btnTextNomalColor forState:UIControlStateNormal]; [btn setTitleColor:self.btnTextSeletedColor forState:UIControlStateSelected]; [btn setTitle:vc.title forState:UIControlStateNormal]; [btn addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside]; [self.topBar addSubview:btn]; if(i == 0) { btn.selected = YES; self.oldBtn = btn; } } self.topBar.contentSize = CGSizeMake(self.btnW *count, -64); } -(void)addVCView { UIScrollView *contentView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0+44, SCREEN_WIDTH, SCREEN_HEIGHT -44)]; self.contentView = contentView; self.contentView.bounces = NO; contentView.delegate = self; contentView.backgroundColor = [UIColor colorWithWhite:0.859 alpha:1.000]; [self.view addSubview:contentView]; NSUInteger count = self.VCArr.count; for (int i=0; i<count; i++) { UIViewController *vc = self.VCArr[i]; [self addChildViewController:vc]; vc.view.frame = CGRectMake(i*SCREEN_WIDTH, 0, SCREEN_WIDTH, SCREEN_HEIGHT -44); [contentView addSubview:vc.view]; } contentView.contentSize = CGSizeMake(count*SCREEN_WIDTH, SCREEN_HEIGHT - 44); contentView.pagingEnabled = YES; } -(void)click:(UIButton *)sender { if(sender.selected) return; self.oldBtn.selected = NO; sender.selected = YES; self.contentView.contentOffset = CGPointMake((sender.tag - 10000) *SCREEN_WIDTH, 0); self.oldBtn.transform = CGAffineTransformIdentity; self.oldBtn = sender; //判断导航条是否需要移动 CGFloat maxX = CGRectGetMaxX(self.slider.frame); if(maxX >=SCREEN_WIDTH && sender.tag != self.VCArr.count + 10000 - 1) { [UIView animateWithDuration:0.3 animations:^{ self.topBar.contentOffset = CGPointMake(maxX - SCREEN_WIDTH + self.btnW, -64); }]; }else if(maxX < SCREEN_WIDTH) { [UIView animateWithDuration:0.3 animations:^{ self.topBar.contentOffset = CGPointMake(0, 0); }]; } } -(void)scrollViewDidScroll:(UIScrollView *)scrollView { //滑动导航条 self.slider.frame = CGRectMake(scrollView.contentOffset.x / SCREEN_WIDTH *self.btnW + 25 , 41, self.btnW - 50, 3); } //判断是否切换导航条按钮的状态 -(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { CGFloat offX = scrollView.contentOffset.x; int tag = (int)(offX /SCREEN_WIDTH + 0.5) + 10000; UIButton *btn = [self.view viewWithTag:tag]; if(tag != self.oldBtn.tag) { [self click:btn]; } } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } @end</code></pre> <h3><strong>这个很容易看懂的, 是不是, 就不在这里多解释.</strong></h3> <p style="text-align:center"><img src="https://simg.open-open.com/show/505cdeacd9a718c7e63245c39dee11df.png"></p> <p>上面这张呢, 则是把导航栏隐藏, 自定义一个小UIView截取网络图片作为导航栏, 又自定义一个大View作为tableView头视图.并且我还运用了观察者注册消息通知, 代码有点长, 不过我写注释了哦, 可以看懂的.</p> <pre> <code class="language-objectivec">// // BookMarksViewController.m // HotTopic // // Created by dllo on 16/9/7. // Copyright © 2016年 高雅馨. All rights reserved. // #import "BookMarksViewController.h" #import "HTMacro.h" #import "UIView+Extension.h" #import "BookTableViewCell.h" #import "EssayViewController.h" #import "SubscriberViewController.h" #import "UMSocial.h" #import "DCNavTabBarController.h" #import "UIImageView+WebCache.h" #import "AFNetworking.h" #import "HotTopicsModel.h" #import "TopicModel.h" #import "NodeModel.h" #import "UserModel.h" #import "Source.h" #import "DisposeViewController.h" #import "HeadImageView.h" static CGFloat const headViewHeight = 280; @interface BookMarksViewController ()<UITableViewDelegate,UITableViewDataSource> @property (nonatomic, strong) BookTableViewCell * mainTableView; @property (nonatomic, strong) HeadImageView * headImageView;//头部图片 @property (nonatomic, strong) UIImageView * avatarImage; @property (nonatomic, strong) UILabel * countentLabel; @property (nonatomic, strong) UIImageView *img; @property (nonatomic, strong) HotTopicsModel *hotTopic; @property (nonatomic, strong) UILabel *titleLabel; @property (nonatomic, assign) BOOL canScroll; @property (nonatomic, assign) BOOL isTopIsCanNotMoveTabView; @property (nonatomic, assign) BOOL isTopIsCanNotMoveTabViewPre; @property (nonatomic, strong) UIView *barView; @property (nonatomic, strong) UILabel *titleText; @end @implementation BookMarksViewController @synthesize mainTableView; - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; [self.navigationController setNavigationBarHidden:YES]; } - (void)viewDidLoad { [super viewDidLoad]; // 这个api功能就是在NavigationController堆栈内的UIViewController可以支持右滑手势,也就是不用点击右上角的返回按钮,轻轻在屏幕左边一 滑,屏幕就会返回,随着ios设备屏幕的增大,这个小功能让手指短,拇指大和手残人士看到了福音。 self.navigationController.interactivePopGestureRecognizer.delegate = (id)self; [self.navigationController setNavigationBarHidden:YES]; self.automaticallyAdjustsScrollViewInsets = NO; [self.view addSubview:self.mainTableView]; // 设置tableView头视图 self.mainTableView.tableHeaderView = self.headImageView; // 将导航栏隐藏使其变为透明 [self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault]; // 将导航栏那条黑线隐藏 [self.navigationController.navigationBar setShadowImage:[UIImage new]]; /** 观察者注册消息通知 */ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(leaveTop:) name:@"leaveTop" object:nil]; [self creatView]; } // 把导航栏写成自定义View - (void)creatView { _barView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, 64)]; UIButton *backButton = [UIButton buttonWithType:UIButtonTypeCustom]; backButton.frame = CGRectMake(10, 30, 30, 30); [backButton setImage:[UIImage imageNamed:@"backBar"] forState:UIControlStateNormal]; [backButton addTarget:self action:@selector(clickBackBtn:) forControlEvents:UIControlEventTouchUpInside]; UIButton *shareBtn = [UIButton buttonWithType:UIButtonTypeCustom]; shareBtn.frame = CGRectMake(SCREEN_WIDTH - 50, 30, 30, 30); [shareBtn setImage:[UIImage imageNamed:@"shareBar"] forState:UIControlStateNormal]; [shareBtn addTarget:self action:@selector(clickShareBtn:) forControlEvents:UIControlEventTouchUpInside]; _titleText = [[UILabel alloc] initWithFrame:CGRectMake(50, 30, SCREEN_WIDTH - 100, 30)]; _titleText.text = @"收藏夹"; _titleText.textAlignment = 1; _titleText.textColor = [UIColor whiteColor]; // 毛玻璃效果 UIBlurEffect *blur = [UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight]; UIVisualEffectView *effectview = [[UIVisualEffectView alloc] initWithEffect:blur]; effectview.backgroundColor = [UIColor colorWithWhite:0.508 alpha:1.000]; effectview.alpha = 0.65; effectview.frame = CGRectMake(0, 0, SCREEN_WIDTH, 64); [_barView addSubview:effectview]; [_barView addSubview:backButton]; [_barView addSubview:shareBtn]; [_barView addSubview:_titleText]; [self.view addSubview:_barView]; } /** * notificationObserver 观察者 : self * notificationSelector 处理消息的方法名: getUserProfileSuccess * notificationName 消息通知的名字: Notification_GetUserProfileSuccess * notificationSender 消息发送者 : 表示接收哪个发送者的通知,如果第四个参数为nil,接收所有发送者的通知 */ - (void)leaveTop:(NSNotification *)notification{ NSDictionary *userInfo = notification.userInfo; NSString *canScroll = userInfo[@"canScroll"]; if ([canScroll isEqualToString:@"1"]) { _canScroll = YES; } } /** 将自定义View的背景图设置tableView头视图的背景图*/ - (UIImage *)clipImageInOffsetY:(CGFloat)y { if (_headImageView.image == nil) { return [UIImage new]; } CGRect rect = CGRectMake(0, y, SCREEN_WIDTH, 64); CGImageRef imageRef = CGImageCreateWithImageInRect([_headImageView.image CGImage], rect); self.blurView.frame = CGRectMake(0, 0, SCREEN_WIDTH, 64); self.blurView.alpha = 0.7; [self.navigationController.navigationBar addSubview:_blurView]; UIImage *thumbScale = [UIImage imageWithCGImage:imageRef]; return thumbScale; } // 用scrollView的偏移量来判断 - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ CGFloat yOffset = scrollView.contentOffset.y; if (yOffset >= _headImageView.height - 64) { yOffset = _headImageView.height - 64; } UIImage *image = [self clipImageInOffsetY:yOffset]; _barView.backgroundColor = [UIColor colorWithPatternImage:image]; //获取滚动视图y值的偏移量 self.navigationController.navigationBar.alpha = (headViewHeight+yOffset)/(headViewHeight-64); CGFloat tabOffsetY = [mainTableView rectForSection:0].origin.y - 64.0f; CGFloat offsetY = scrollView.contentOffset.y; _isTopIsCanNotMoveTabViewPre = _isTopIsCanNotMoveTabView; if (offsetY >= tabOffsetY) { //不能滑动 scrollView.contentOffset = CGPointMake(0, tabOffsetY); _isTopIsCanNotMoveTabView = YES; _titleText.text = self.urlTitle; }else{ //可以滑动 _isTopIsCanNotMoveTabView = NO; _titleText.text = @"收藏夹"; } if (_isTopIsCanNotMoveTabView != _isTopIsCanNotMoveTabViewPre) { if (!_isTopIsCanNotMoveTabViewPre && _isTopIsCanNotMoveTabView) { [[NSNotificationCenter defaultCenter] postNotificationName:@"goTop" object:nil userInfo:@{@"canScroll":@"1"}]; _canScroll = NO; } if(_isTopIsCanNotMoveTabViewPre && !_isTopIsCanNotMoveTabView){ if (!_canScroll) { scrollView.contentOffset = CGPointMake(0, tabOffsetY); } } } } // 头视图 - (UIImageView *)headImageView { if (_headImageView == nil) { _headImageView = [[HeadImageView alloc]initWithFrame:CGRectMake(0, 0,SCREEN_WIDTH,headViewHeight)]; _headImageView.userInteractionEnabled = YES; [_headImageView sd_setImageWithURL:[NSURL URLWithString:self.urlHeadImg] placeholderImage:[UIImage imageNamed:@"touxiang"]completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { }]; UIBlurEffect *blur = [UIBlurEffect effectWithStyle:UIBlurEffectStyleExtraLight]; UIVisualEffectView *effectview = [[UIVisualEffectView alloc] initWithEffect:blur]; effectview.backgroundColor = [UIColor colorWithWhite:0.508 alpha:1.000]; effectview.alpha = 0.7; effectview.frame = CGRectMake(0, 0, SCREEN_WIDTH, headViewHeight); [_headImageView addSubview:effectview]; self.navigationController.hidesBarsOnSwipe = NO; _avatarImage = [[UIImageView alloc] initWithFrame:CGRectMake(20, 20 + 64, SCREEN_WIDTH / 3.3, SCREEN_WIDTH / 3.3)]; [_headImageView addSubview:_avatarImage]; _avatarImage.userInteractionEnabled = YES; _avatarImage.layer.masksToBounds = YES; [ _avatarImage sd_setImageWithURL:[NSURL URLWithString:self.urlHeadImg] placeholderImage:[UIImage imageNamed:@"detailViewDefaultMidImage"]]; _countentLabel = [[UILabel alloc] initWithFrame:CGRectMake(_avatarImage.frame.size.width + 40, 20 + 64, SCREEN_WIDTH - (SCREEN_WIDTH / 3 + 20 + 10), _avatarImage.frame.size.height / 4)]; _countentLabel.font = [UIFont systemFontOfSize:15]; _countentLabel.textColor = [UIColor whiteColor]; _countentLabel.lineBreakMode = NSLineBreakByWordWrapping; _countentLabel.numberOfLines = 0; _countentLabel.text = self.urlTitle; [_headImageView addSubview:_countentLabel]; _img = [[UIImageView alloc] initWithFrame:CGRectMake(_countentLabel.frame.origin.x, _countentLabel.frame.size.height + _avatarImage.frame.origin.y + 10, 30, 30)]; _img.layer.cornerRadius = 15; _img.layer.masksToBounds = YES; _img.backgroundColor = [UIColor yellowColor]; [_headImageView addSubview:_img]; _titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(_img.frame.size.width + _img.frame.origin.x + 5, _img.frame.origin.y, SCREEN_WIDTH / 1.9 , 30)]; _titleLabel.textColor = [UIColor whiteColor]; _titleLabel.lineBreakMode = NSLineBreakByWordWrapping; _titleLabel.numberOfLines = 0; _titleLabel.font = [UIFont systemFontOfSize:12]; [_headImageView addSubview:_titleLabel]; UILabel *contextLabel = [[UILabel alloc] initWithFrame:CGRectMake(_img.frame.origin.x , _img.frame.origin.y + _img.frame.size.height + 6, SCREEN_WIDTH / 2 , SCREEN_WIDTH / 8)]; contextLabel.textColor = [UIColor whiteColor]; contextLabel.text = self.urlContect; contextLabel.lineBreakMode = NSLineBreakByWordWrapping; contextLabel.numberOfLines = 0; contextLabel.font = [UIFont systemFontOfSize:12]; [_headImageView addSubview:contextLabel]; UIButton *takeBtn = [UIButton buttonWithType:UIButtonTypeSystem]; takeBtn.frame = CGRectMake(_img.frame.origin.x - 20 , contextLabel.frame.size.height + contextLabel.frame.origin.y + 10, SCREEN_WIDTH / 4, _avatarImage.frame.size.height / 3.2); [takeBtn setTitle:@"+ 订阅" forState:UIControlStateNormal]; [takeBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; takeBtn.backgroundColor = [UIColor colorWithRed:1.00 green:0.36 blue:0.25 alpha:1.00]; takeBtn.titleLabel.font = [UIFont systemFontOfSize:14]; takeBtn.layer.cornerRadius = 10; [_headImageView addSubview:takeBtn]; UIButton *contributeBtn = [UIButton buttonWithType:UIButtonTypeSystem]; contributeBtn.frame = CGRectMake(takeBtn.frame.origin.x + takeBtn.frame.size.width + 5, contextLabel.frame.size.height + contextLabel.frame.origin.y + 10, SCREEN_WIDTH / 8, _avatarImage.frame.size.height / 3.2); [contributeBtn setTitle:@"投稿" forState:UIControlStateNormal]; [contributeBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; contributeBtn.layer.borderWidth = 1.0; contributeBtn.titleLabel.font = [UIFont systemFontOfSize:14]; contributeBtn.layer.borderColor = [UIColor whiteColor].CGColor; contributeBtn.layer.cornerRadius = 5; [_headImageView addSubview:contributeBtn]; UIButton *manageLabel = [[UIButton alloc] initWithFrame:CGRectMake(contributeBtn.frame.size.width + contributeBtn.frame.origin.x, contributeBtn.frame.origin.y + 5, SCREEN_WIDTH / 5 , 30)]; [manageLabel setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal]; [manageLabel setTitle:@"0未处理☞" forState:UIControlStateNormal]; manageLabel.titleLabel.textAlignment = 0; manageLabel.titleLabel.font = [UIFont systemFontOfSize:12]; [manageLabel addTarget:self action:@selector(clickManageBtn:) forControlEvents:UIControlEventTouchUpInside]; [_headImageView addSubview:manageLabel]; } return _headImageView; } // 大tableView -(UITableView *)mainTableView { if (mainTableView == nil) { mainTableView= [[BookTableViewCell alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH,SCREEN_HEIGHT)]; mainTableView.delegate = self; mainTableView.dataSource=self; mainTableView.bounces = NO; mainTableView.separatorStyle = UITableViewCellSeparatorStyleNone; mainTableView.showsVerticalScrollIndicator = NO; mainTableView.backgroundColor = [UIColor clearColor]; mainTableView.rowHeight = SCREEN_HEIGHT; } return mainTableView; } #pragma marl -tableDelegate - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return 1; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{ return SCREEN_HEIGHT; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil]; cell.selectionStyle = UITableViewCellSelectionStyleNone; //添加pageView [cell.contentView addSubview:self.setPageViewControllers]; return cell; } // 调用两个小VC -(UIView *)setPageViewControllers{ EssayViewController *essay = [[EssayViewController alloc] init]; essay.urlStr = self.urlStr; essay.title = [NSString stringWithFormat:@"文章\n%@", self.articleCount]; SubscriberViewController *subscribe = [[SubscriberViewController alloc] init]; subscribe.urlStr = self.urlStr; subscribe.title = [NSString stringWithFormat:@"订阅者\n%@", self.subscriberCount]; NSArray *subViewControllers=@[essay, subscribe]; DCNavTabBarController *tabBarVC = [[DCNavTabBarController alloc]initWithSubViewControllers:subViewControllers]; tabBarVC.view.frame = CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT); [self.view addSubview:tabBarVC.view]; [self addChildViewController:tabBarVC]; return tabBarVC.view; } @end</code></pre> <h3><strong>写到这里, 就完成了, 下面让我们来看一下成果吧!</strong></h3> <p style="text-align:center"><img src="https://simg.open-open.com/show/433c234748ffc8a2838c6096095f8a7c.gif"></p> <p>是不是特别棒呢, 喜欢的话就来试试看吧!��有什么不足和建议可以评论哦, 我会虚心接受的, 喜欢给个赞:+1:哦!</p> <p> </p> <p>来自:http://www.jianshu.com/p/825fc83fc311</p> <p> </p>