OC 技术 UIPageViewController 小说的翻页效果(源码)

news/2024/7/20 23:03:22 标签: ios

一直觉得自己写的不是技术,而是情怀,一个个的教程是自己这一路走来的痕迹。靠专业技能的成功是最具可复制性的,希望我的这条路能让你们少走弯路,希望我能帮你们抹去知识的蒙尘,希望我能帮你们理清知识的脉络,希望未来技术之巅上有你们也有我。

(OC)小说翻页效果,UIPageViewController-代码事例

视频解说
在这里插入图片描述

效果

请添加图片描述

前言

整个页面的代码原理就是一个ViewController,上面添加了一个UIPageViewController,然后UIPageViewController上面在加一个ViewController,当手势翻下一页的时候就调用UIPageViewController的datasource返回NextViewController,当手势前下一页的时候就调用UIPageViewController的datasource返回BackViewController,

定义属性

//翻页控制器
@property (strong, nonatomic) UIPageViewController *pageViewController;
@property (strong, nonatomic) NSArray *pageData;//1-12数组 数据源方法
//保存当前控制器的目的是为了,翻页的时候,用当前控制器拿到当前的页数,看看是否有下一页或者前一页
@property (nonatomic, strong) UIViewController *currentViewController;

初始化 UIPageViewController

初始化 UIPageViewController和数据源

    self.pageData = @[@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"10",@"11",@"12"];

    self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
    self.pageViewController.delegate = self;
    self.pageViewController.dataSource = self;
    self.pageViewController.doubleSided = NO;//用于确定页面是否具有双面显示。将显示前一页和后一页的内容
    
    NextViewController *startingViewController = [self viewControllerAtIndex:0];
    NSArray *viewControllers = @[startingViewController];
    [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:NULL];
 

    [self addChildViewController:self.pageViewController];
    [self.view addSubview:self.pageViewController.view];
    self.pageViewController.view.frame = self.view.bounds;
    [self.pageViewController didMoveToParentViewController:self];

    // Add the page view controller's gesture recognizers to the book view controller's view so that the gestures are started more easily.
    self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;

实现 UIPageViewController 的代理方法

// 该方法用于告诉UIPageViewController在不同设备方向下(例如横向或纵向)如何设置页面的脊柱(spine),即两个页面之间的间隔。
- (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation
{
    // 获取当前的视图控制器
    UIViewController *currentViewController = self.pageViewController.viewControllers[0];
    
    // 将当前视图控制器放入数组中
    NSArray *viewControllers = @[currentViewController];
    
    // 设置UIPageViewController的视图控制器为当前视图控制器,并指定方向为向前,带有动画效果
    [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];

    // 设置UIPageViewController为双面显示
    self.pageViewController.doubleSided = YES;
    
    // 返回页面脊柱的位置为最小值
    return UIPageViewControllerSpineLocationMin;
}

实现 UIPageViewController 的数据源方法

#pragma mark - UIPageViewController dataSource methods
// UIPageViewController数据源方法

// 前一页
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
    // 如果当前页是NextViewController类型
    if([viewController isKindOfClass:[NextViewController class]]) {
        // 将当前视图控制器设置为当前控制器
        self.currentViewController = viewController;
        
        // 创建BackViewController实例
        BackViewController *backViewController = [[BackViewController alloc] init];
        // 更新BackViewController的视图控制器
        [backViewController updateWithViewController:viewController];
        return backViewController;
    }
    
    // 获取当前页的索引
    NSUInteger index = [self indexOfViewController:(NextViewController *)_currentViewController];
    // 如果当前页是第一页或者索引未找到,则返回nil
    if ((index == 0) || (index == NSNotFound)) {
        return nil;
    }
    
    // 索引减1,返回相应索引的视图控制器
    index--;
    return [self viewControllerAtIndex:index];
}

// 后一页
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
    // 如果当前页是NextViewController类型
    if([viewController isKindOfClass:[NextViewController class]]) {
        // 将当前视图控制器设置为当前控制器
        self.currentViewController = viewController;
        
        // 创建BackViewController实例
        BackViewController *backViewController = [[BackViewController alloc] init];
        // 更新BackViewController的视图控制器
        [backViewController updateWithViewController:viewController];
        return backViewController;
    }
    
    // 获取当前页的索引
    NSUInteger index = [self indexOfViewController:(NextViewController *)_currentViewController];
    // 如果索引未找到,则返回nil
    if (index == NSNotFound) {
        return nil;
    }
    
    // 索引加1
    index++;
    // 如果索引等于数据源总数,则返回nil
    if (index == [self.pageData count]) {
        return nil;
    }
    // 返回相应索引的视图控制器
    return [self viewControllerAtIndex:index];
}

定义两个私有方法

传入当前页数,返回当前页数的控制器(包括内容)

#pragma mark - 私有方法 - 传入当前页数,返回当前页数的控制器(包括内容)
- (NextViewController *)viewControllerAtIndex:(NSUInteger)index {
    if (([self.pageData count] == 0) || (index >= [self.pageData count])) {
        return nil;
    }

    NextViewController *dataViewController = [NextViewController new];
    dataViewController.value = self.pageData[index];
    return dataViewController;
}

获取当前控制器的当前页数,用于滑动时判断是否有下一页和前一页

#pragma mark - 私有方法 - 获取当前控制器的当前页数,用于滑动时判断是否有下一页和前一页
- (NSUInteger)indexOfViewController:(NextViewController *)viewController {
    return [self.pageData indexOfObject:viewController.value];
}

前一个控制器

里面定义了一个方法,用于图片的内容翻页是的翻页效果

- (void)updateWithViewController:(UIViewController *)viewController {
    self.backgroundImage = [self captureView:viewController.view];
}

// 捕捉指定视图的内容并返回 UIImage 对象
- (UIImage *)captureView:(UIView *)view {
    // 获取视图的边界
    CGRect rect = view.bounds;
    // 开始一个图形上下文
    UIGraphicsBeginImageContextWithOptions(rect.size, YES, 0.0f);
    // 获取当前图形上下文
    CGContextRef context = UIGraphicsGetCurrentContext();
    // 创建仿射变换,用于翻转图像
    CGAffineTransform transform = CGAffineTransformMake(-1.0, 0.0, 0.0, 1.0, rect.size.width, 0.0);
    // 将仿射变换应用于当前图形上下文
    CGContextConcatCTM(context,transform);
    // 在当前图形上下文中渲染视图的层
    [view.layer renderInContext:context];
    // 从当前图形上下文中获取图像
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    // 结束图形上下文
    UIGraphicsEndImageContext();
    // 返回捕捉到的图像
    return image;
}

下一个控制器

下一个控制器比较简单里面就一个label现实小说的内容

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor colorWithRed:241.0/255.0 green:243.0/255.0 blue:247.0/255.0 alpha:1.0];
    //正页内容例如是一个label文本
    self.dataLabel = [UILabel new];
    self.dataLabel.text = self.value;
    self.dataLabel.textColor = [UIColor blackColor];
    self.dataLabel.addTo(self.view).fnt(16).makeCons(^{
        make.center.equal.view(self.view);
    });
}

http://www.niftyadmin.cn/n/5472732.html

相关文章

Plonky2.5:在Plonky2中验证Plonky3 proof

1. 引言 Plonky2.5为QED Protocol团队主导的项目,定位为: 在Plonky2 SNARK中验证Plonky3 STARK proof。 从而实现Plonky系列的递归证明。 开源代码实现见: https://github.com/QEDProtocol/plonky2.5https://github.com/Plonky3/Plonky3&a…

【UnityRPG游戏制作】Unity_RPG项目之界面面板分离和搭建

👨‍💻个人主页:元宇宙-秩沅 👨‍💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨‍💻 本文由 秩沅 原创 👨‍💻 收录于专栏:Uni…

彩虹聚合DNS管理系统,附带系统搭建教程

聚合DNS管理系统,可以实现在一个网站内管理多个平台的域名解析,目前已支持的域名平台有:阿里云、腾讯云、华为云、西部数码、CloudFlare。 本系统支持多用户,每个用户可分配不同的域名解析权限;支持API接口&#xff0…

2024年ERP管理系统职业技能大赛软件测试赛项-销售专员模块Bug清单

目录 一、ERP管理系统说明: 二、销售专员模块部分Bug缺陷清单: 一、ERP管理系统说明: ERP(资源协同)管理平台将采购、销售、库存、服务等活动紧密衔接在一起,提供完整供应链服务࿰

MATLAB实现数值求解高阶常微分方程组

一、高阶常微分方程组 高阶常微分方程是指包含多个高阶常微分方程的系统。这些方程通常涉及多个未知函数及其高阶导数。解决高阶常微分方程组通常比解决单个高阶常微分方程更为复杂,因为需要同时考虑多个方程和多个未知函数之间的关系。 一般来说,解决…

传输层 --- TCP (下篇)

目录 1. 超时重传 1.1. 数据段丢包 1.2. 接收方发送的ACK丢包 1.3. 超时重传的超时时间如何设置 2. 流量控制 3. 滑动窗口 3.1. 初步理解滑动窗口 3.2. 滑动窗口的完善理解 3.3. 关于快重传的补充 3.4. 快重传和超时重传的区别 4. 拥塞控制 4.1. 拥塞控制的宏观认识…

java——文件上传

一、文件上传——简介 文件上传的简介:文件上传是指将本地计算机中的文件传输到网络上的服务器或另一台计算机上的过程。在 Web 开发中,文件上传通常指的是将用户通过 Web 页面提交的文件(如图像、文档、音频、视频等)传输到服务器…

突破编程_C++_C++14新特性(auto 类型推断)

1 C11 中的 auto 类型回顾 auto 类型是 C11 中引入的一个关键字,用于自动类型推导。这意味着编译器会根据初始化的表达式自动确定变量的类型。使用 auto 可以让代码更简洁、易读,同时减少类型错误。 (1)auto 的基本用法 使用 a…