Ответ 1
Обновление: см. Редактировать 3 для ответа на исходный вопрос
Есть два варианта:
-
Используйте библиотеку для преобразования HTML в PDF. Это, безусловно, лучший вариант, поскольку он (вероятно) сохранит текст в виде векторов.
-
Получите рендеринг высокого разрешения HTML и сохраните его как PNG (не PDF, конечно!).
Для HTML в PDF wkhtmltopdf выглядит неплохо, но он полагается на Qt, который вы не можете использовать на Android, Есть некоторые другие библиотеки, но я сомневаюсь, что они очень хорошо выполняют PDF-рендеринг.
Для получения веб-представления с высоким разрешением вы можете попробовать создать свой собственный WebView
и вызвать onMeasure(...)
и onLayout(...)
и передать соответствующие параметры, чтобы представление было действительно большим. Затем вызовите onDraw(myOwnCanvas)
, и веб-просмотр будет привязан к вашему холсту, который может быть подкреплен Bitmap
с помощью Canvas.setBitmap()
.
Скорее всего вы можете скопировать состояние в новый WebView
, используя что-то вроде
screenshotterWebview.onRestoreInstanceState(mWebView.onSaveInstanceState());
Orrr, возможно, будет возможно использовать тот же WebView
, просто временно измените его размер на большой, onDraw()
на его холст и снова измените его размер. Это становится очень хаки!
Вы можете столкнуться с проблемами памяти, если вы сделаете ее слишком большой.
Изменить 1
Я подумал о третьем, точно-то, что вы хотите, но это вроде хардкор. Вы можете создать пользовательский Canvas
, который записывает в PDF файл. Фактически, это почти легко, поскольку базовый Canvas
- это Skia, который фактически включает в себя PDF-архив. К сожалению, у вас нет доступа к нему на Android, поэтому вам в основном нужно будет создать свою собственную копию на Android (есть инструкции) и дублировать/переопределять все методы Canvas
, чтобы указать на вашу Skia вместо Андроиды. Обратите внимание, что существует соблазнительный метод Picture.writeToStream()
, который сериализует данные Skia, но, к сожалению, этот формат не является передовым или обратным, поэтому, если вы его используете, ваш код, вероятно, будет работать только в нескольких версиях Android.
Я буду обновлять, если/когда у меня есть полностью рабочий код.
Изменить 2
На самом деле невозможно сделать свой собственный "перехват" Canvas
. Я начал делать это и прошел через утомительный процесс сериализации всех вызовов функций. Некоторые из них вы не можете сделать, потому что они скрыты, но они не выглядели важными. Но в конце я пришел к сериализации Path
только для того, чтобы обнаружить, что он написан только для записи. Для меня это похоже на убийцу, поэтому единственным вариантом является интерпретация результата Picture.writeToStream()
. К счастью, используются только две версии этого формата, и они почти идентичны.
Редактировать 3 - Действительно простой способ получить изображение Bitmap
с высоким разрешением
Хорошо, получается, что получение растрового изображения с высоким разрешением (которое может быть всем приложением) тривиально. Вот как получить двойное разрешение. Очевидно, что все растровые изображения выглядят немного дерьмовыми, но текст отображается в полном разрешении:
View window = activity.getWindow().getDecorView()
Canvas bitmapCanvas = new Canvas();
Bitmap bitmap = Bitmap.createBitmap(window.getWidth()*2, window.getHeight()*2, Bitmap.Config.ARGB_8888);
bitmapCanvas.setBitmap(bitmap);
bitmapCanvas.scale(2.0f, 2.0f);
window.draw(bitmapCanvas);
bitmap.compress(Bitmap.CompressFormat.PNG, 0, myOutputStream);
Работает как шарм. Теперь я отказался от получения скриншота PDF с векторным текстом. Это, конечно, возможно, но очень сложно. Вместо этого я работаю над получением PSD с высоким разрешением, где каждая операция рисования является отдельным слоем, что должно быть намного проще.
Изменить 4
Woa это становится немного длиннее, но успех! Я создал .xcf
(GIMP) и PDF, где каждый слой - это другая операция рисования холста. Это не совсем так, как я ожидал, но все же, очень полезно!
На самом деле мой код просто выводит полноразмерные PNG, и я использовал "Open as layers..." и "Autocrop layer" в GIMP для создания этих файлов, но, конечно, вы можете сделать это в коде, если хотите. Я думаю, что я превращу это в сообщение в блоге.
Загрузите демонстрационный файл GIMP или Photoshop (отображается с разрешением 3 раза).