iOS實(shí)現(xiàn)PDF文件瀏覽功能
寫(xiě)了一個(gè)小Demo,顯示本地PDF格式文件,支持翻頁(yè)、跳頁(yè)、縮放。
先看一下效果圖:

iOS開(kāi)發(fā),顯示PDF格式文件方法有很多:
- 最簡(jiǎn)單的應(yīng)該是UIWebView,可以加載本地或網(wǎng)絡(luò)PDF文件,支持上下滑動(dòng)瀏覽、縮放。
- 優(yōu)化一點(diǎn)的是用系統(tǒng)的QLPreviewController加載,實(shí)現(xiàn)起來(lái)也比較方便,支持上下滑動(dòng)瀏覽,左后滑動(dòng)可多PDF文件切換,同時(shí)支持原生的分享打印,QLPreviewController支持的文檔格式也比較多,如pdf、doc、docx、xls、xlsx、txt、ppt、mp4...
- 上面兩種都沒(méi)有足夠的自定義空間,不在這里做過(guò)多的介紹了,另外一種也就是本篇用到的iOS核心圖形庫(kù):Core Graphics,繪制PDF文檔。
簡(jiǎn)單說(shuō)一下邏輯,根據(jù)本地路徑獲取到CGPDFDocumentRef,在drawRect中繪制上下文,畫(huà)出PDF文件。通過(guò)UIScrollView實(shí)現(xiàn)縮放,添加UIGestureRecognizer實(shí)現(xiàn)單擊、雙擊、左滑、右滑功能?;贑ATransition實(shí)現(xiàn)翻頁(yè)動(dòng)畫(huà)。
下面貼上核心代碼:
承載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;
//創(chuàng)建控件
[self creatControl];
}
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
//防止隱藏導(dǎo)航時(shí),左滑返回導(dǎo)航消失
CGRect temNavBarFrame = self.navigationController.navigationBar.frame;
temNavBarFrame.origin.y = 20;
self.navigationController.navigationBar.frame = temNavBarFrame;
}
- (void)creatControl
{
//導(dǎo)航右側(cè)按鈕
UIButton *deleteBtn = [[UIButton alloc] initWithFrame:CGRectMake(9, 0, 40, 40)];
deleteBtn.titleLabel.font = [UIFont systemFontOfSize:16.f];
[deleteBtn setTitle:@"跳頁(yè)" 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);
}
//根據(jù)縮放調(diào)整
_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];
//右滑手勢(shì)
UISwipeGestureRecognizer *rightSwip = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(nextPage)];
rightSwip.direction = UISwipeGestureRecognizerDirectionLeft;
[scrollView addGestureRecognizer:rightSwip];
//左滑手勢(shì)
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;
//允許翻頁(yè)的偏移量
CGFloat movePadding = 70.f;
//仿蘋(píng)果原生相冊(cè),圖片放大后,滑動(dòng)前在邊界時(shí)在可以翻頁(yè),這里加了±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];
}
}
//滑動(dòng)自然停止時(shí)調(diào)用
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
_lastScrContX = scrollView.contentOffset.x;
}
//滑動(dòng)手動(dòng)停止時(shí)調(diào)用
- (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);
}
//上一頁(yè)
- (void)prePage
{
if(_currentPage < 2) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"已經(jīng)第一頁(yè)了!" delegate:self cancelButtonTitle:@"確定" otherButtonTitles: nil ];
[alert show];
return;
}
--_currentPage;
[self reloadView];
[self transitionWithType:@"pageUnCurl" WithSubtype:kCATransitionFromRight ForView:self];
}
//下一頁(yè)
- (void)nextPage
{
if(_currentPage >= _totalPages) {
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"提示" message:@"已經(jīng)最后一頁(yè)了!" delegate:self cancelButtonTitle:@"確定" otherButtonTitles: nil ];
[alert show];
return;
}
++_currentPage;
[self reloadView];
[self transitionWithType:@"pageCurl" WithSubtype:kCATransitionFromRight ForView:self];
}
//設(shè)置翻頁(yè)動(dòng)畫(huà)效果
- (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 下載鏈接
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
iOS實(shí)現(xiàn)換膚功能的簡(jiǎn)單處理框架(附源碼)
這篇文章主要給大家介紹了關(guān)于iOS實(shí)現(xiàn)換膚功能的簡(jiǎn)單處理框架,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-02-02
iOS中tableview 兩級(jí)cell的展開(kāi)與收回的示例代碼
本篇文章主要介紹了iOS中tableview 兩級(jí)cell的展開(kāi)與收回的示例代碼,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-03-03
iOS中的UISearchBar搜索框組件基礎(chǔ)使用指南
iOS開(kāi)發(fā)套件中自帶的UISearchBar搜索框我們平時(shí)經(jīng)常可以用到,我們可以在默認(rèn)的基礎(chǔ)上修改文字顏色、背景顏色和背景圖片等,這里我們稍微總結(jié)一下iOS中的UISearchBar搜索框組件基礎(chǔ)使用指南.2016-05-05
Unity3d發(fā)布IOS9應(yīng)用時(shí)出現(xiàn)中文亂碼的解決方法
這里給大家分享的是使用UNity3d發(fā)布IOS9應(yīng)用的時(shí)候,遇到出現(xiàn)中文亂碼的現(xiàn)象的解決方法,核心內(nèi)容非常簡(jiǎn)單就是批量修改NGUI的label字體,下面把代碼奉上。2015-10-10
iOS 高效的分頁(yè)加載實(shí)現(xiàn)示例
本篇文章主要介紹了iOS 高效的分頁(yè)加載實(shí)現(xiàn)示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-10-10

