iOS实现PDF文件浏览功能

写了一个小Demo,显示本地PDF格式文件,支持翻页、跳页、缩放。 

先看一下效果图:

iOS开发,显示PDF格式文件方法有很多:

  • 最简单的应该是UIWebView,可以加载本地或网络PDF文件,支持上下滑动浏览、缩放。
  • 优化一点的是用系统的QLPreviewController加载,实现起来也比较方便,支持上下滑动浏览,左后滑动可多PDF文件切换,同时支持原生的分享打印,QLPreviewController支持的文档格式也比较多,如pdf、doc、docx、xls、xlsx、txt、ppt、mp4...
  • 上面两种都没有足够的自定义空间,不在这里做过多的介绍了,另外一种也就是本篇用到的iOS核心图形库:Core Graphics,绘制PDF文档。

简单说一下逻辑,根据本地路径获取到CGPDFDocumentRef,在drawRect中绘制上下文,画出PDF文件。通过UIScrollView实现缩放,添加UIGestureRecognizer实现单击、双击、左滑、右滑功能。基于CATransition实现翻页动画。

下面贴上核心代码:

承载PDF文件视图的控制器:HWPDFBrowseVC

#import <UIKit/UIKit.h>

@interface HWPDFBrowseVC : UIViewController

@property (nonatomic, copy) NSString *filePath;

@property (nonatomic, copy) NSString *fileName;

@end

/*** ---------------分割线--------------- ***/

#import "HWPDFBrowseVC.h"

#import "HWPDFBrowseView.h"

#import "HWPDFBrowseToolBar.h"

#import "HWPDFBrowseScrollView.h"

#define KPicMaxScale 3.0

#define KMainW [UIScreen mainScreen].bounds.size.width

#define KMainH [UIScreen mainScreen].bounds.size.height

@interface HWPDFBrowseVC ()<UIScrollViewDelegate, HWPDFBroeseToolBarDelegate>

@property (nonatomic, weak) HWPDFBrowseScrollView *scrollView;

@property (nonatomic, weak) HWPDFBrowseView *browseView;

@property (nonatomic, weak) HWPDFBrowseToolBar *toolBar;

@property (nonatomic, assign) CGFloat minZoomScale;

@property (nonatomic, assign) CGFloat lastScrContX;

@end

@implementation HWPDFBrowseVC

- (void)viewDidLoad {

[super viewDidLoad];

//初始化

self.view.backgroundColor = [UIColor whiteColor];

self.navigationItem.title = _fileName;

//创建控件

[self creatControl];

}

- (void)viewWillDisappear:(BOOL)animated

{

[super viewWillDisappear:animated];

//防止隐藏导航时,左滑返回导航消失

CGRect temNavBarFrame = self.navigationController.navigationBar.frame;

temNavBarFrame.origin.y = 20;

self.navigationController.navigationBar.frame = temNavBarFrame;

}

- (void)creatControl

{

//导航右侧按钮

UIButton *deleteBtn = [[UIButton alloc] initWithFrame:CGRectMake(9, 0, 40, 40)];

deleteBtn.titleLabel.font = [UIFont systemFontOfSize:16.f];

[deleteBtn setTitle:@"跳页" forState:UIControlStateNormal];

[deleteBtn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];

[deleteBtn addTarget:self action:@selector(navBtnOnClick) forControlEvents:UIControlEventTouchUpInside];

UIView *rightView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 40, 40)];

[rightView addSubview:deleteBtn];

self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:rightView];

//scrollView

HWPDFBrowseScrollView *scrollView = [[HWPDFBrowseScrollView alloc] initWithFrame:[UIScreen mainScreen].bounds];

scrollView.delegate = self;

scrollView.backgroundColor = [UIColor blackColor];

scrollView.maximumZoomScale = KPicMaxScale;

scrollView.showsVerticalScrollIndicator = NO;

scrollView.showsHorizontalScrollIndicator = NO;

[self.view addSubview:scrollView];

_scrollView = scrollView;

//pdf视图

HWPDFBrowseView *browseView = [[HWPDFBrowseView alloc] initWithFilePath:_filePath];

[scrollView addSubview:browseView];

_browseView = browseView;

//绘制pdf视图后缩放至屏幕完全居中显示

CGRect frame = browseView.frame;

frame.size.width = browseView.frame.size.width > KMainW ? KMainW : browseView.frame.size.width;

frame.size.height = frame.size.width * (browseView.frame.size.height / browseView.frame.size.width);

if (frame.size.height > KMainH) {

frame.size.height = KMainH;

frame.size.width = KMainH * (browseView.frame.size.width / browseView.frame.size.height);

}

//根据缩放调整

_minZoomScale = frame.size.width / browseView.frame.size.width;

scrollView.allowScrollScale = _minZoomScale;

scrollView.minimumZoomScale = _minZoomScale;

scrollView.zoomScale = _minZoomScale;

//底部工具栏

HWPDFBrowseToolBar *toolBar = [[HWPDFBrowseToolBar alloc] initWithFrame:CGRectMake(0, KMainH - 49, KMainW, 49) currentPage:_browseView.currentPage totalPage:_browseView.totalPages];

toolBar.delegate = self;

[self.view addSubview:toolBar];

_toolBar = toolBar;

//单击

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(click)];

tap.numberOfTouchesRequired = 1;

tap.numberOfTapsRequired = 1;

[scrollView addGestureRecognizer:tap];

//双击

UITapGestureRecognizer *tapDouble = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(doubleClick)];

tapDouble.numberOfTapsRequired = 2;

[scrollView addGestureRecognizer:tapDouble];

[tap requireGestureRecognizerToFail:tapDouble];

//右滑手势

UISwipeGestureRecognizer *rightSwip = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(nextPage)];

rightSwip.direction = UISwipeGestureRecognizerDirectionLeft;

[scrollView addGestureRecognizer:rightSwip];

//左滑手势

UISwipeGestureRecognizer *leftSwip = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(forwardPage)];

leftSwip.direction = UISwipeGestureRecognizerDirectionRight;

[scrollView addGestureRecognizer:leftSwip];

}

- (void)navBtnOnClick

{

[_toolBar showWindow];

}

//单击屏幕显示隐藏菜单

- (void)click

{

CGFloat navBarY = _toolBar.frame.origin.y == KMainH - 49 ? -64 : 20;

CGFloat toolBarY = _toolBar.frame.origin.y == KMainH - 49 ? KMainH : KMainH - 49;

[UIView animateWithDuration:0.25 animations:^{

CGRect temNavBarFrame = self.navigationController.navigationBar.frame;

temNavBarFrame.origin.y = navBarY;

self.navigationController.navigationBar.frame = temNavBarFrame;

CGRect temToolBarFrame = _toolBar.frame;

temToolBarFrame.origin.y = toolBarY;

_toolBar.frame = temToolBarFrame;

}];

}

//双击屏幕放大缩小图片

- (void)doubleClick

{

[UIView animateWithDuration:0.25f animations:^{

_scrollView.zoomScale = _scrollView.zoomScale == _minZoomScale ? KPicMaxScale : _minZoomScale;

}];

}

//左滑事件

- (void)nextPage

{

[_browseView nextPage];

_toolBar.currentPage = _browseView.currentPage;

}

//右滑事件

- (void)forwardPage

{

[_browseView prePage];

_toolBar.currentPage = _browseView.currentPage;

}

#pragma mark - UICouseBrowseToolBarDelegate

- (void)browseToolBar:(HWPDFBrowseToolBar *)browseToolBar didClickFinishButtonWithPage:(NSString *)page

{

_browseView.currentPage = [page integerValue];

[_browseView reloadView];

[_toolBar dismissKeyboard];

_scrollView.zoomScale = _minZoomScale;

}

- (void)browseToolBar:(HWPDFBrowseToolBar *)browseToolBar didPageButtonWithAction:(BOOL)nextPage

{

if (nextPage) {

[self nextPage];

}else {

[self forwardPage];

}

_scrollView.zoomScale = _minZoomScale;

}

#pragma mark - UIScrollViewDelegate

- (void)scrollViewDidZoom:(UIScrollView *)scrollView

{

CGFloat offsetX = (scrollView.bounds.size.width > scrollView.contentSize.width) ? (scrollView.bounds.size.width - scrollView.contentSize.width) * 0.5 : 0.0;

CGFloat offsetY = (scrollView.bounds.size.height > scrollView.contentSize.height) ? (scrollView.bounds.size.height - scrollView.contentSize.height) * 0.5 : 0.0;

_browseView.center = CGPointMake(scrollView.contentSize.width * 0.5 + offsetX, scrollView.contentSize.height * 0.5 + offsetY - 64);

}

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView

{

return _browseView;

}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView

{

if (scrollView.isZooming) return;

//允许翻页的偏移量

CGFloat movePadding = 70.f;

//仿苹果原生相册,图片放大后,滑动前在边界时在可以翻页,这里加了±10的偏移量

if (scrollView.contentOffset.x < - movePadding && _lastScrContX < 10) {

_scrollView.zoomScale = _minZoomScale;

[self forwardPage];

}

if (scrollView.contentSize.width - scrollView.contentOffset.x < KMainW - movePadding && scrollView.contentSize.width != 0 && fabsf(_lastScrContX + KMainW - scrollView.contentSize.width) < 10) {

_scrollView.zoomScale = _minZoomScale;

[self nextPage];

}

}

//滑动自然停止时调用

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

{

_lastScrContX = scrollView.contentOffset.x;

}

//滑动手动停止时调用

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate

{

_lastScrContX = scrollView.contentOffset.x;

}

- (void)didReceiveMemoryWarning {

[super didReceiveMemoryWarning];

// Dispose of any resources that can be recreated.

}

@end

PDF文件视图:HWPDFBrowseView

#import <UIKit/UIKit.h>

@interface HWPDFBrowseView : UIView{

CGPDFDocumentRef pdfDocumentRef;

}

@property (nonatomic, assign) NSInteger currentPage;

@property (nonatomic, assign) NSInteger totalPages;

- (id)initWithFilePath:(NSString *)filePath;

- (void)reloadView;

- (void)prePage;

- (void)nextPage;

@end

/*** ---------------分割线--------------- ***/

#import "HWPDFBrowseView.h"

@implementation HWPDFBrowseView

- (id)initWithFilePath:(NSString *)filePath

{

pdfDocumentRef = [self createPDFFromExistFile:filePath];

self = [super initWithFrame:CGPDFPageGetBoxRect(CGPDFDocumentGetPage(pdfDocumentRef, 1), kCGPDFMediaBox)];

return self;

}

- (CGPDFDocumentRef)createPDFFromExistFile:(NSString *)aFilePath

{

CFStringRef path = CFStringCreateWithCString(NULL, [aFilePath UTF8String], kCFStringEncodingUTF8);

CFURLRef urlRef = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, NO);

CFRelease(path);

CGPDFDocumentRef document = CGPDFDocumentCreateWithURL(urlRef);

CFRelease(urlRef);

_totalPages = CGPDFDocumentGetNumberOfPages(document);

_currentPage = 1;

if (_totalPages == 0) return NULL;

return document;

}

- (void)reloadView

{

[self setNeedsDisplay];

}

- (void)drawRect:(CGRect)rect

{

CGContextRef context = UIGraphicsGetCurrentContext();

[[UIColor whiteColor] set];

CGContextFillRect(context, rect);

CGContextTranslateCTM(context, 0.0, rect.size.height);

CGContextScaleCTM(context, 1.0, -1.0);

CGPDFPageRef page = CGPDFDocumentGetPage(pdfDocumentRef, _currentPage);

CGAffineTransform pdfTransform = CGPDFPageGetDrawingTransform(page, kCGPDFCropBox, rect, 0, true);

CGContextConcatCTM(context, pdfTransform);

CGContextDrawPDFPage(context, page);

}

//上一页

- (void)prePage

{

if(_currentPage < 2) {

UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"已经第一页了!" delegate:self cancelButtonTitle:@"确定" otherButtonTitles: nil ];

[alert show];

return;

}

--_currentPage;

[self reloadView];

[self transitionWithType:@"pageUnCurl" WithSubtype:kCATransitionFromRight ForView:self];

}

//下一页

- (void)nextPage

{

if(_currentPage >= _totalPages) {

UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"已经最后一页了!" delegate:self cancelButtonTitle:@"确定" otherButtonTitles: nil ];

[alert show];

return;

}

++_currentPage;

[self reloadView];

[self transitionWithType:@"pageCurl" WithSubtype:kCATransitionFromRight ForView:self];

}

//设置翻页动画效果

- (void)transitionWithType:(NSString *)type WithSubtype:(NSString *)subtype ForView:(UIView *)view

{

CATransition *animation = [CATransition animation];

animation.duration = 0.7f;

animation.type = type;

if (subtype) animation.subtype = subtype;

animation.timingFunction = UIViewAnimationOptionCurveEaseInOut;

[view.layer addAnimation:animation forKey:@"animation"];

}

@end

Demo 下载链接

以上是 iOS实现PDF文件浏览功能 的全部内容, 来源链接: utcz.com/z/350847.html

回到顶部