网易新闻首页

知识点

首先是上下两个科滚动的视图,可以用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中新建一个空白文件即可)

新建.m文件

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;

results matching ""

    No results matching ""