Неожиданные разрывы страниц при печати UIWebView
TL;DR: Если вы печатаете UIWebView
, который содержит HTML
контент, состоящий из элементов с выравниванием текста right
/center
, в результате документ будет иметь страницы с неожиданно большими нижними полями.
Я столкнулся с этой проблемой и был очень удивлен, когда не смог найти никого с подобной проблемой. Я подал радар с яблоком (# 20760071), а также создал issue в ResearchKit
GitHub repo, так как это влияет на их ORKHTMLPDFWriter
.
AFAIK это также влияет на все библиотеки, которые используют 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);
}];
Вы также можете клонировать проект, демонстрируя эту проблему в 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>
Однако ни одно из вышеперечисленных действий не подходит для выравнивания текста переменной длины, который является основным прецедентом, с которым я связан.
Ответы
Ответ 1
Вано,
Решение, которое я придумал после некоторого тестирования, заключается в добавлении следующих правил CSS с выравниванием текста.
display: -webkit-box;
display: -webkit-flex;
display: flex;
justify-content: flex-end;
-webkit-justify-content: flex-end;
text-align:right;
Ответ 2
Мое решение для выравнивания текста: справа
<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>
Ответ 3
Я предполагаю, что это не сработает с выравниванием текста переменной длины, потому что длина текста, очевидно, постоянно изменяется, где ваш обходной атрибут div
имеет статический атрибут width
.
Это задание для замены строки, заменив разделитель width
на размер бумаги (чтобы поля заполнили текстом). Чтобы получить эту ширину, вызовите это:
pc.printPaper.printRect.size.width;
Но для его замены у вас должен быть делегат, чтобы исправить код HTML до начала задания.
Назначьте ли ваш делегат новый объект класса из типа NSObject
в качестве подкласса в Xcode File Creator, а затем у вас есть функция для запуска принтера и отображения содержимого в этом представлении:
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 по какой-то причине. Я еще не закончил!)
В классе делегата я попросил вас сделать до, сделайте этот файл .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
Он возвращает исключение плохого доступа, но вы получаете суть: после того, как пользователь выбирает их тип бумаги, установите разделитель width
в ширину области печати. Единственный другой вариант - либо иметь указанную ширину (например, вы предложили в своем редактировании), либо иметь одну конкретную бумагу, которую пользователь может распечатать.
Причина, по которой это происходит, связана с ошибкой при печати HTML-кода UIWebView
, а не из-за кодирования. Надеюсь, Apple исправляет это в более позднем обновлении.