网易新闻首页
知识点
首先是上下两个科滚动的视图,可以用UIScrollView来控制显示。
1.首先显示上面导航栏的视图
self.titleScrollView.showsHorizontalScrollIndicator = NO;这句话必须设置在contentSize之后,才会起作用,在初始化方法中没有作用。
2.添加控制器为当前控制器的子控制器
// 这里只是添加控制器,实际上控制器上的view并没有添加,因为控制器上的view是懒加载添加
JXOneController * one = [[JXOneController alloc] init];
one.title = @"政治";
[self addChildViewController:one];
3.UIScrollViewDelegte
部分代理方法是认为操作的时候才会调用,代码操作的时候是没办法调用的
#pragma mark - UIScrollViewDelegate
// 这个方法只是在人为拖动界面的时候才会调用,代码添加的不会调用
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
NSLog(@"%s",__func__);
}
如果是代码操作的话我们需要调用
// scrollView 结束滚动的时候就会调用这个方法,比如([self.contentVc setContentOffset:offset animated:YES])执行完毕之后就会调用,这个方法当手动拖动的时候是不会调用
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
NSLog(@"%s",__func__);
}
4.点击导航栏上操作在scrollview上添加控制器的view有两种办法
1.重新定义一个变量来保存每次点击的位置
2.直接用偏移量来计算当前位置
实现
AppDelegate.h
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
AppDelegate.m
#import "AppDelegate.h"
#import "JXNavController.h"
#import "JXMainController.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
JXMainController * main = [[JXMainController alloc] init];
JXNavController * nav = [[JXNavController alloc] initWithRootViewController:main];
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.rootViewController = nav;
[self.window makeKeyAndVisible];
return YES;
}
自定义导航栏
JXNavController.h
#import <UIKit/UIKit.h>
@interface JXNavController : UINavigationController
@end
JXNavController.m
#import "JXNavController.h"
@interface JXNavController ()
@end
@implementation JXNavController
- (void)viewDidLoad {
[super viewDidLoad];
}
@end
主控制器
JXMainController.h
#import <UIKit/UIKit.h>
@interface JXMainController : UIViewController
@end
JXMainController.m
#import "JXMainController.h"
#import "JXOneController.h"
#import "JXTwoController.h"
#import "JXThreeController.h"
#import "JXFourController.h"
#import "JXFiveController.h"
#import "JXSixController.h"
#import "JXSevenController.h"
#import "UIView+Frame.h"
@interface JXMainController ()<UIScrollViewDelegate>
/** 标题栏 */
@property (nonatomic,weak) UIScrollView * titleScrollView;
/** 内容栏 */
@property (nonatomic,weak) UIScrollView * contentVc;
@end
@implementation JXMainController
- (void)viewDidLoad {
[super viewDidLoad];
self.automaticallyAdjustsScrollViewInsets = NO;
[self setupAddChilds];
[self setupTitleVc];
[self setupContentVc];
// 直接默认显示第一个
[self scrollViewDidEndScrollingAnimation:self.contentVc];
}
#pragma mark - 创建页面
/**
* 创建导航界面
*/
- (void)setupTitleVc {
// 一共7个控件
NSInteger count = 7;
// 控件宽高
CGFloat width = 80.0;
CGFloat height = 30.0;
CGFloat x = 0;
CGFloat y = 0;
for (NSInteger i = 0; i<count; i++) {
UILabel * label = [[UILabel alloc] init];
x = i * width;
label.frame = CGRectMake(x, y, width, height);
label.textAlignment = NSTextAlignmentCenter;
label.userInteractionEnabled = YES;
// 取出当前控制器的title,命名导航栏
label.text = [self.childViewControllers[i] title];
// label添加tag值
label.tag = i;
// label添加点按手势
UITapGestureRecognizer * tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tap:)];
[label addGestureRecognizer:tap];
label.backgroundColor = [self randColor];
[self.titleScrollView addSubview:label];
}
self.titleScrollView.contentSize = CGSizeMake(count * width, 0);
self.titleScrollView.showsHorizontalScrollIndicator = NO;
// 设置内容视图的大小
self.contentVc.contentSize = CGSizeMake(count * self.view.width, 0);
}
/**
* 创建内容界面
*/
- (void)setupContentVc {
UISwitch * sw = [[UISwitch alloc] init];
sw.center = self.view.center;
[self.contentVc addSubview:sw];
UISwitch * sw2 = [[UISwitch alloc] init];
sw2.centerX = 90;
sw2.centerY = 300;
[self.contentVc addSubview:sw2];
UISwitch * sw3 = [[UISwitch alloc] init];
sw3.centerX = 500;
sw3.centerY = 300;
[self.contentVc addSubview:sw3];
}
/**
* 点击事件
*/
- (void)tap:(UITapGestureRecognizer *)gesture {
NSLog(@"%s",__func__);
// 取出点击tag值
NSInteger index = gesture.view.tag;
// 根据tag值偏移内容视图
CGPoint offset = self.contentVc.contentOffset;
offset.x = index * self.view.width;
[self.contentVc setContentOffset:offset animated:YES];
}
#pragma mark - 添加控制器
- (void)setupAddChilds {
// 这里只是添加控制器,实际上控制器上的view并没有添加,因为控制器上的view是懒加载添加
JXOneController * one = [[JXOneController alloc] init];
one.title = @"政治";
[self addChildViewController:one];
JXTwoController * two = [[JXTwoController alloc] init];
two.title = @"军事";
[self addChildViewController:two];
JXThreeController * three = [[JXThreeController alloc] init];
three.title = @"教育";
[self addChildViewController:three];
JXFourController * four = [[JXFourController alloc] init];
four.title = @"财经";
[self addChildViewController:four];
JXFiveController * five = [[JXFiveController alloc] init];
five.title = @"社会";
[self addChildViewController:five];
JXSixController * six = [[JXSixController alloc] init];
six.title = @"国际";
[self addChildViewController:six];
JXSevenController * seven = [[JXSevenController alloc] init];
seven.title = @"民生";
[self addChildViewController:seven];
}
#pragma mark - 懒加载
- (UIScrollView *)titleScrollView {
if (_titleScrollView == nil) {
UIScrollView * titleScrollView = [[UIScrollView alloc] init];
titleScrollView.frame = CGRectMake(0, 64, self.view.width, 30);
titleScrollView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:titleScrollView];
_titleScrollView = titleScrollView;
}
return _titleScrollView;
}
- (UIScrollView *)contentVc {
if (_contentVc == nil) {
UIScrollView * contentScrollView = [[UIScrollView alloc] init];
contentScrollView.frame = CGRectMake(0, 94, self.view.width, self.view.height - 94);
[self.view addSubview:contentScrollView];
contentScrollView.backgroundColor = [UIColor orangeColor];
contentScrollView.pagingEnabled = YES;
contentScrollView.delegate = self;
_contentVc = contentScrollView;
}
return _contentVc;
}
#pragma mark - 颜色
- (UIColor *)randColor {
CGFloat r = arc4random_uniform(256) / 255.0;
CGFloat g = arc4random_uniform(256) / 255.0;
CGFloat b = arc4random_uniform(256) / 255.0;
return [UIColor colorWithRed:r green:g blue:b alpha:1.0];
}
#pragma mark - UIScrollViewDelegate
// 这个方法只是在人为拖动界面的时候才会调用,代码添加的不会调用
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
[self scrollViewDidEndScrollingAnimation:scrollView];
}
// scrollView 结束滚动的时候就会调用这个方法,比如([self.contentVc setContentOffset:offset animated:YES])执行完毕之后就会调用
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
// 当前需要显示的控制器索引
NSInteger index = scrollView.contentOffset.x / scrollView.width;
// 取出当前控制器
UIViewController * willShowVc = self.childViewControllers[index];
// 如果当前控制器已经显示过了,我们就不需要再次进行计算它的frame,可以直接返回
if ([willShowVc isViewLoaded]) return;
// 另一种办法
// if (willShowVc.view.superview) return;
// 计算控制器view的frame
willShowVc.view.frame = CGRectMake(scrollView.contentOffset.x, 0, scrollView.width, scrollView.height);
[self.contentVc addSubview:willShowVc.view];
}
@end
重点
// scrollView 结束滚动的时候就会调用这个方法,比如([self.contentVc setContentOffset:offset animated:YES])执行完毕之后就会调用
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
// 当前需要显示的控制器索引
NSInteger index = scrollView.contentOffset.x / scrollView.width;
// 取出当前控制器
UIViewController * willShowVc = self.childViewControllers[index];
// 如果当前控制器已经显示过了,我们就不需要再次进行计算它的frame,可以直接返回
if ([willShowVc isViewLoaded]) return;
// 另一种办法
// if (willShowVc.view.superview) return;
// 计算控制器view的frame
willShowVc.view.frame = CGRectMake(scrollView.contentOffset.x, 0, scrollView.width, scrollView.height);
[self.contentVc addSubview:willShowVc.view];
}
当下部分内容控制器移动的时候,需要上面的导航标题栏的对应的标题移动到视图中间,但是左边跟右边是不可以移动的
思路:
当在最左边的时候,只需要判断标题按钮的对应的label的中心点-屏幕宽度的一半与0的关系,如果小于0那么在左边偏移量最小就是为0;
公式:self.label.centerX - self.view.width * 0.5 < 0
当在右边的时候,最大偏移量标题按钮的内容contentSize的大小 - 屏幕宽度
最大值:self.scrollView.contentSize - self.view.width
设置上下两个UIScrollView来控制两个控件,一个是上部分的标题,一个是上部分的content
问题:当直接选中上面的标题并点击,然后让下面的内容视图跟随之改变,但是这里会有一个问题就:是当直接选中最上面靠右,然后标题按钮随之一起改变,但是在滚动过程中,可能有在开始和结束之间会有别的颜色产生
解决:
在选中之后的其他按钮统统设置为规定的字体
在项目中引用其他常量
这里推荐使用extern
1.先新建一个header头文件
2.头文件默认内容(需删除)
3.头文件重写内容,这里写我们需要在外部引用的常量
4.一般还需要再次新建一个.m文件(这里在Other中新建一个空白文件即可)
5.新建.m文件需要自己在新建的时候添加XXX.m
6.在空白文件中写入我们设置的常量
在其中const修饰的是不可以改变的常量,在引用的时候只需要在需要引用的文件中导入.h头文件即可
头文件设置
JXConst.h
#import <UIKit/UIKit.h>
UIKIT_EXTERN const CGFloat JXRed;
UIKIT_EXTERN const CGFloat JXRed;
UIKIT_EXTERN const CGFloat JXRed;
UIKIT_EXTERN const CGFloat JXRed;
UIKIT_EXTERN const CGFloat JXRed;
UIKIT_EXTERN就是extern,只是为了装逼
JXConst.m
#import <UIKit/UIKit.h>
const CGFloat JXRed = 1.0;