打印 UIWebView 时意外分页
Unexpected page breaks when printing UIWebView
TLDR: 如果打印 UIWebView
其中包含 HTML
内容,其中包含文本对齐 right
/ center
的元素, 生成的文档的页面底部边距会出乎意料地大。
我遇到了这个问题,当我无法 google 任何有类似问题的人时,我感到非常惊讶。我已经向 apple (#20760071) 提交了雷达,还在 ResearchKit
的 GitHub 回购中创建了一个 issue,因为这会影响他们的 ORKHTMLPDFWriter
。
据我所知,这也会影响所有使用 UIWebView
将 HTML
转换为 PDF
的库,我已经测试过:
我想知道是否有人可以想出一些解决方法。
重现方式:
NSMutableString* html = [NSMutableString string];
[html appendString:@"<html><body>"];
for (int i=0; i<200; i++) {
[html appendString:@"<div align=\"right\">line</div>"];
}
[html appendString:@"</body></html>"];
UIPrintInteractionController* pc = [UIPrintInteractionController sharedPrintController];
UIPrintInfo* printInfo = [UIPrintInfo printInfo];
printInfo.outputType = UIPrintInfoOutputGrayscale;
pc.printInfo = printInfo;
pc.showsPaperSelectionForLoadedPapers = YES;
UIWebView* web = [UIWebView new];
[web loadHTMLString:html baseURL:nil];
pc.printFormatter = web.viewPrintFormatter;
[pc presentAnimated:YES completionHandler:^(UIPrintInteractionController *printInteractionController, BOOL completed, NSError *error) {
NSLog(@"%d -- %@",completed, error);
}];
您还可以克隆 project 在 ResearchKit
中演示此问题。
编辑 - 一些可用的解决方法:
知道内容(例如图像)的特定宽度,可以在不指定文本对齐方式的情况下对其进行对齐,例如:
使用自动边距:
<div>
<div style="width:200px; margin-left:auto; margin-right:0px;">
content
</div>
</div>
浮动列:
<div>
<div style="width:200px; float:right;">
content
</div>
</div>
但是,上面的 none 用于对齐可变长度文本,这是我关心的主要用例。
我认为这不适用于对齐可变长度文本,因为文本的长度显然在不断变化,而您的解决方法的 div
属性具有静态 width
属性。
这是一个字符串替换作业,将分隔线的 width
替换为纸张尺寸(以允许边距填充文本)。要获得此宽度,请调用:
pc.printPaper.printRect.size.width;
但是,为了替换它,您需要有一个代表在那里修复 HTML 代码 就在作业开始之前。
让你的委托成为 NSObject
类型的新 class 对象作为 Xcode 文件创建器中的子 class,然后让你的函数触发打印机和渲染内容在您看来与此类似:
NSMutableString* html = [NSMutableString string];
[html appendString:@"<html><body>"];
for (int i=0; i<200; i++) {
[html appendString:@"temporary content... "];
}
[html appendString:@"</body></html>"];
UIWebView* web = [UIWebView new];
[web loadHTMLString:html baseURL:nil];
UIPrintInteractionController* pc = [UIPrintInteractionController sharedPrintController];
pc.printFormatter = web.viewPrintFormatter;
UIPrintInfo* printInfo = [UIPrintInfo printInfo];
printInfo.outputType = UIPrintInfoOutputGrayscale;
printerDelegate* pd = [printerDelegate new];
pc.printInfo = printInfo;
pc.showsPaperSelectionForLoadedPapers = YES;
pc.delegate = pd;
[pc presentAnimated:YES completionHandler:^(UIPrintInteractionController *printInteractionController, BOOL completed, NSError *error) {
NSLog(@"%d -- %@",completed, error);
}];
(注意:我在 HTML 文件中制作临时内容是有原因的。我还没有完成!)
在 委托 class 之前我要求你制作,制作这个 .h
文件:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface printerDelegate : NSObject <UIPrintInteractionControllerDelegate>
@end
然后,在它的 .m
文件中,我有这个...
#import "printerDelegate.h"
#import <UIKit/UIKit.h>
@implementation printerDelegate
-(void)printInteractionControllerWillDismissPrinterOptions:(UIPrintInteractionController *)printInteractionController {
@try {
NSMutableString* html = [NSMutableString string];
[html appendString:@"<html><body>"];
for (int i=0; i<200; i++) {
[html appendString:[NSString stringWithFormat:@"<div><div style=""width:%fpx; margin-left:auto; margin-right:0px;"">content</div></div>", printInteractionController.printPaper.printRect.size.width]];
}
[html appendString:@"</body></html>"];
UIWebView* web = [UIWebView new];
[web loadHTMLString:html baseURL:nil];
printInteractionController.printFormatter = web.viewPrintFormatter;
}
@catch (NSException *exception) {
NSLog(@"%@", exception.debugDescription);
}
@finally {
}
}
@end
它 returns 是一个错误的访问异常,但您明白了要点:在用户选择他们的纸张类型后,将分隔符的 width
设置为打印区域的宽度。唯一的其他选择是要么具有指定的宽度(就像您在编辑中建议的那样),要么具有用户可以打印的特定类型的纸张。
发生这种情况的原因是打印 UIWebView
的 HTML 时出现错误,而不是因为编码。希望 Apple 在以后的更新中修复此问题。
瓦诺,
经过一些测试后我想出的解决方案是添加以下 css 文本对齐规则。
display: -webkit-box;
display: -webkit-flex;
display: flex;
justify-content: flex-end;
-webkit-justify-content: flex-end;
text-align:right;
我对 text-align:right 的解决方案
<header>
<style type="text/css">
.default-text-align-right {
text-align: right;
}
.alternative-text-align-right {
position: absolute;
right: 10px;
}
</style>
</header>
<body>
<div>
<div class="default-text-align-right">
Default Text Align Left
</div>
<div>
<div class="alternative-text-align-right">Alternative Text Align Right</div>
<div> </div>
</div>
<div class="default-text-align-right">
Default Text Align Left
</div>
</div>
</body>
TLDR: 如果打印 UIWebView
其中包含 HTML
内容,其中包含文本对齐 right
/ center
的元素, 生成的文档的页面底部边距会出乎意料地大。
我遇到了这个问题,当我无法 google 任何有类似问题的人时,我感到非常惊讶。我已经向 apple (#20760071) 提交了雷达,还在 ResearchKit
的 GitHub 回购中创建了一个 issue,因为这会影响他们的 ORKHTMLPDFWriter
。
据我所知,这也会影响所有使用 UIWebView
将 HTML
转换为 PDF
的库,我已经测试过:
我想知道是否有人可以想出一些解决方法。
重现方式:
NSMutableString* html = [NSMutableString string];
[html appendString:@"<html><body>"];
for (int i=0; i<200; i++) {
[html appendString:@"<div align=\"right\">line</div>"];
}
[html appendString:@"</body></html>"];
UIPrintInteractionController* pc = [UIPrintInteractionController sharedPrintController];
UIPrintInfo* printInfo = [UIPrintInfo printInfo];
printInfo.outputType = UIPrintInfoOutputGrayscale;
pc.printInfo = printInfo;
pc.showsPaperSelectionForLoadedPapers = YES;
UIWebView* web = [UIWebView new];
[web loadHTMLString:html baseURL:nil];
pc.printFormatter = web.viewPrintFormatter;
[pc presentAnimated:YES completionHandler:^(UIPrintInteractionController *printInteractionController, BOOL completed, NSError *error) {
NSLog(@"%d -- %@",completed, error);
}];
您还可以克隆 project 在 ResearchKit
中演示此问题。
编辑 - 一些可用的解决方法:
知道内容(例如图像)的特定宽度,可以在不指定文本对齐方式的情况下对其进行对齐,例如:
使用自动边距:
<div>
<div style="width:200px; margin-left:auto; margin-right:0px;">
content
</div>
</div>
浮动列:
<div>
<div style="width:200px; float:right;">
content
</div>
</div>
但是,上面的 none 用于对齐可变长度文本,这是我关心的主要用例。
我认为这不适用于对齐可变长度文本,因为文本的长度显然在不断变化,而您的解决方法的 div
属性具有静态 width
属性。
这是一个字符串替换作业,将分隔线的 width
替换为纸张尺寸(以允许边距填充文本)。要获得此宽度,请调用:
pc.printPaper.printRect.size.width;
但是,为了替换它,您需要有一个代表在那里修复 HTML 代码 就在作业开始之前。
让你的委托成为 NSObject
类型的新 class 对象作为 Xcode 文件创建器中的子 class,然后让你的函数触发打印机和渲染内容在您看来与此类似:
NSMutableString* html = [NSMutableString string];
[html appendString:@"<html><body>"];
for (int i=0; i<200; i++) {
[html appendString:@"temporary content... "];
}
[html appendString:@"</body></html>"];
UIWebView* web = [UIWebView new];
[web loadHTMLString:html baseURL:nil];
UIPrintInteractionController* pc = [UIPrintInteractionController sharedPrintController];
pc.printFormatter = web.viewPrintFormatter;
UIPrintInfo* printInfo = [UIPrintInfo printInfo];
printInfo.outputType = UIPrintInfoOutputGrayscale;
printerDelegate* pd = [printerDelegate new];
pc.printInfo = printInfo;
pc.showsPaperSelectionForLoadedPapers = YES;
pc.delegate = pd;
[pc presentAnimated:YES completionHandler:^(UIPrintInteractionController *printInteractionController, BOOL completed, NSError *error) {
NSLog(@"%d -- %@",completed, error);
}];
(注意:我在 HTML 文件中制作临时内容是有原因的。我还没有完成!)
在 委托 class 之前我要求你制作,制作这个 .h
文件:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface printerDelegate : NSObject <UIPrintInteractionControllerDelegate>
@end
然后,在它的 .m
文件中,我有这个...
#import "printerDelegate.h"
#import <UIKit/UIKit.h>
@implementation printerDelegate
-(void)printInteractionControllerWillDismissPrinterOptions:(UIPrintInteractionController *)printInteractionController {
@try {
NSMutableString* html = [NSMutableString string];
[html appendString:@"<html><body>"];
for (int i=0; i<200; i++) {
[html appendString:[NSString stringWithFormat:@"<div><div style=""width:%fpx; margin-left:auto; margin-right:0px;"">content</div></div>", printInteractionController.printPaper.printRect.size.width]];
}
[html appendString:@"</body></html>"];
UIWebView* web = [UIWebView new];
[web loadHTMLString:html baseURL:nil];
printInteractionController.printFormatter = web.viewPrintFormatter;
}
@catch (NSException *exception) {
NSLog(@"%@", exception.debugDescription);
}
@finally {
}
}
@end
它 returns 是一个错误的访问异常,但您明白了要点:在用户选择他们的纸张类型后,将分隔符的 width
设置为打印区域的宽度。唯一的其他选择是要么具有指定的宽度(就像您在编辑中建议的那样),要么具有用户可以打印的特定类型的纸张。
发生这种情况的原因是打印 UIWebView
的 HTML 时出现错误,而不是因为编码。希望 Apple 在以后的更新中修复此问题。
瓦诺,
经过一些测试后我想出的解决方案是添加以下 css 文本对齐规则。
display: -webkit-box;
display: -webkit-flex;
display: flex;
justify-content: flex-end;
-webkit-justify-content: flex-end;
text-align:right;
我对 text-align:right 的解决方案
<header>
<style type="text/css">
.default-text-align-right {
text-align: right;
}
.alternative-text-align-right {
position: absolute;
right: 10px;
}
</style>
</header>
<body>
<div>
<div class="default-text-align-right">
Default Text Align Left
</div>
<div>
<div class="alternative-text-align-right">Alternative Text Align Right</div>
<div> </div>
</div>
<div class="default-text-align-right">
Default Text Align Left
</div>
</div>
</body>