Печать собственных документов

Для некоторых приложений, например графических редакторов, редакторов макетов и других приложений, в которых функции сосредоточены на работе с графикой, создание красивой распечатки – это ключевая функция. В данном случае недостаточно печати изображений или HTML документов. Для вывода на печать в таких приложениях требуется прецизионный контроль во всем, что попадает на страницу печати, включая шрифты, текстовая разметка, разрывы страниц, заголовки, колонтитулы и графические элементы.

Такой персональных подход к печати требует гораздо больше кода, чем мы обсуждали ранее. Вы должны создать компоненты, которые взаимодействуют с интерфейсом печати, приспособиться к настройкам принтера, нарисовать элементы страниц и управлять печать для множества страниц.

В этом уроке мы покажем как присоединиться к менеджеру печати, создать адаптер печати и содержимое для вывода на печать.

Присоединение к менеджеру печати

Если ваше приложение управляет процессом печати, первым делом после получения запроса на печать от пользователя, неоходимо присоединиться к интерфейсу печати Android и получить экземпляр класса PrintManager. Этот класс позволяет инициализировать задание на печать и запускает жизненный цикл печати. Следующий пример показывает как получить менеджер печати и запустить процесс печати:

Код выше демонстрирует, как установить имя задания и выбрать экземпляр класса PrintDocumentAdapter, который будет управлять жизненным циклом печати. Реализация адаптера печати обсуждается в следующем разделе.

Примечание: В качестве последнего параметра метод print() принимает объект типа PrintAttributes. Вы можете использовать эти параметры, чтобы предоставить подсказку интерфейсу печати и выставить предустановленные опции, основанные на предыдущем цикле печати, тем самым улучшая взаимодействие с пользователем. Вы также можете использовать этот параметр для установки опций, более подходящих для текущего содержимого, например установка пейзажной ориентации.

Создание адаптера печати

Адаптер печати взаимодействует с интерфейсом печати Android и выполняет пошагово процесс печати. Этот процесс требует от пользователя выбора принтера и опций печати, прежде чем документ отправится на печать. Этот выбор может повлиять на конечный результат, так как пользователь может выбирать принтеры с разными характеристиками вывода, например с разным размером страниц или разной ориентацией страниц. После выбора принтера, интерфейс печати запрашивает у адаптера формирование документа и подготовку к печати. После нажатия кнопки “печать”, интерфейс печати берет сформированный документ и передает его поставщику печати на вывод. Во время процесса печати пользователь может отменить печать, поэтому адаптер печати должен прослушивать статус и соответствующим образом на него реагировать.

Абстрактный класс PrintDocumentAdapter создан для управления жизненным циклом процесса печати, который имеет четыре метода обратного вызова. Вы должны реализовать эти методы в вашем адаптере печати, чтобы правильно взаимодействовать с интерфейсом печати:

  • onStart() – вызывается как только начинается процесс печати. Если ваше приложение несколько подготовительных задач, например получение отпечатка данных, которые должны быть распечатаны, выполняйте их здесь. Реализация данного метода не обязательна.
  • onLayout() – вызывается каждый раз, когда пользователь меняет настройки печати, которые влияют на вывод, например размер страницы, ориентация, заставляя приложение пересчитывать компоновку страниц для печати. Как минимум этот метод должен возвращать количество страниц, которое ожидается в документе.
  • onWrite() – вызывается для передачи печатных страниц в файл для печати. Этот метод может вызываться один или несколько раз, после каждого вызова метода onLayout().
  • onFinish() – вызывается однократно, в конце процесса печати. Если ваше приложение имеет несколько задач на освобождение ресурсов, выполните их здесь. Метод не является обязательным.

В следующих разделах описано, как реализовать разметку и методы записи, которые критичны для функционирования адаптера печати.

Примечание: эти методы адаптера вызываются в главном потоке вашего приложения. Если вы ожидаете, что в вашей реализации они будут долго выполняться, выделите для них отдельный поток. К примеру, вы можете инкапсулировать процесс подготовки документа к печати в отдельном объекте AsyncTask

Вычисление информации о документе печати

Вместе с реализацией класса PrintDocumentAdapter, ваше приложение должно указать тип документа и подсчитать общее число страниц для печати, информацию о размере страниц. Реализация метода onLayout в адаптере производит эти вычисления и предоставляет информацию о том, что ожидается на выходе в класс PrintDocumentInfo, включая количество страниц и тип данных. Следующий пример показывает базовую реализацию метода onLayout для объекта PrintDocumentAdapter:

Выполнение метода onLayout() может иметь три результата: завершен, отменен и ошибка, в данном случае при ошибке подсчета. Вы должны указывать на результат с помощью вызова соответствующего метода объекта PrintDocumentAdapter.LayoutResultCallback.

Примечание: параметр типа boolean метода onLayoutFinished() показывают изменилась ли разметка содержимого с последнего запроса. Установка этого параметра позволяет интерфейсу печати избегать лишних вызовов метода onWrite(), закэшировав предыдущий документ и тем самым повысив производительность.

Основная работа метода onLayout(), это вычисление количества страниц с учетом атрибутов принтера. Как вы будете вычислять это число, сильно зависит от того, как ваше приложение выводит страницы на печать. Следующий код показывает реализацию, где количество страниц определяется ориентацией печати:

Запись в файл печати

Когда приходит время записывать данные в файл для печати, система вызывает метод onWrite() класса PrintDocumentAdapter. Параметры метода указывают, какие страницы должны быть записаны. Ваша реализация метода должна поместить каждую запрошенную страницу в многостраничный PDF документ. При завершении этого процесса вы вызываете метод onWriteFinished().

Примечание:Интерфейс печати может вызвать метод onWrite() один или несколько раз для каждого вызова метода onLayout(). Поэтому важно установить логический параметр метода onLayoutFinished() в false, если содержимое разметки для печати не изменилось, чтобы избежать лишней перезаписи документа печати.

Следующий пример демонстрирует базовый способ использования класса PrintedPdfDocument для создания PDF файла:

Этот пример оставляет ответственность за прорисовку страниц на методе drawPage, который мы обсудим чуть ниже.

Как и в случае с onLayout(), метод onWrite() может иметь три результата: завершен, отменен, ошибка, в данном случае, если содержимое не смогло записаться. Вы должны указывать на эти результаты с помощью вызова соответствующих методов объекта PrintDocumentAdapter.WriteResultCallback.

Примечание: отрисовка документа для печати может быть очень ресурсоемкой операцией. Для того, чтобы избежать блокировки потока пользовательского интерфейса, вы должны выполнять отрисовку страниц и операцию записи в отдельном потоке, например в AsyncTask. Подробную информацию о работе с потоками для асинхронных задач читайте в разделе Процессы и потоки.

Отрисовка PDF страницы

Ваше приложение должно генерировать PDF документ и передавать его в интерфейс печати Android. Вы можете использовать для этих целей библиотеку генерации PDF. В этом уроке мы расскажем, как использовать класс PrintedPdfDocument для генерации PDF из ваших данных.

Класс PrintedPdfDocument использует объект типа Canvas для отрисовки элементов PDF страниц, также как при рисовании на разметке явления. Вы можете нарисовать элементы на странице для печати используя методы класса Canvas. В следующем примере показано как нарисовать некоторые простые элементы на PDF странице, используя эти методы:

При использовании Canvas для рисования на страницах PDF, элементы рассчитываются в точках, который равны 1/72 дюйма. Убедитесь, что используете эту единицу измерения для указания размеров элементов на странице. Координаты точки (0;0) для позиционирования элементов, расположена в верхнем левом углу страницы.

Совет: в то время, как Canvas позволяет рисовать элементы в углах PDF документа, многие принтеры не позволяют печатать на физическом краю бумаги. Таким образом, вы сами несете ответственность за непечатаемые углы при подготове документа.

Добавить комментарий