Подтвердить что ты не робот

Неожиданные разрывы страниц при печати 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>

Однако ни одно из вышеперечисленных действий не подходит для выравнивания текста переменной длины, который является основным прецедентом, с которым я связан.

4b9b3361

Ответ 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>&nbsp;</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 исправляет это в более позднем обновлении.