当前位置: 首页 > news >正文

Android Pdf文档的生成、显示与打印

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

Android 6.0带来了好多功能,PDF的读取展示就是其中一项


一.PDF文档的生成

 DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
 // create a new document
 PdfDocument document = new PdfDocument();//当然,我们也可以使用PrintedPdfDocument,后者继承自前者
 // crate a page description

for(int i=0;i<mPageCount;i++){

 PageInfo pageInfo = new PageInfo.Builder(new Rect(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels), (i+1)).create();
 // start a page
 Page page = document.startPage(pageInfo);
 // draw something on the page
 View content = getContentView();
//将View的UI会知道Canvas上
 content.draw(page.getCanvas());
 // finish the page
 document.finishPage(page);
}
FileOutputStream fos = new FileOutStream("/storage/cache/mypage.pdf");
 document.writeTo(fos );
 // close the document
 document.close();

二.PDF文档读取与显示(配合ViewPager使用)

ParcelFileDescriptor pfdesc =  ParcelFileDescriptor.open(new File('/storage/cache/mypage.pdf',ParcelFileDescriptor.MODE_READ_ONLY));
PdfRender pdfRender = new PdfRender(pfdesc);

List<Bitmap> mlist = new ArrayList<Bitmap>();  //此处职位示例,正式项目请使用懒加载,否则可能导致OOM

if(pdfRender.getPageCount()>0)
{
   for(int i=0;i<pdfRender.getPageCount();i++)
   {
     PdfRender.Page  page =  pdfRender.openPage(i);
     Bitmap bmp = Bitmap.createBitmap(page.getWidth(),
        page.getHeight(), Bitmap.Config.RGB_565)
        
        page.render(bmp, null,new Matrix() ,PdfRender.Page.RENDER_MODE_FOR_DISPLAY);
        
        page.close();
        
        mlist.add(bmp);
   }
   
   pdfRender.close();
}

三.打印PDF文档

打印pdf先要生成pdf打印文档,其次需要使用打印管理器

 PrintManager printManager = (PrintManager) context.getSystemService(Context.PRINT_SERVICE);
 printManager.print(String printJobName, PrintDocumentAdapter documentAdapter, PrintAttributes attributes)

当然,我们需要完成PrintDocumentAdapter

public class MyPrintDocumentAdapter extends PrintDocumentAdapter
{
	Context context;
    	private int pageHeight;
    	private int pageWidth;
    	public PdfDocument myPdfDocument; 
    	public int totalpages = 4;
		
	public MyPrintDocumentAdapter(Context context)
	{
		this.context = context;
	}
		
	@Override
	public void onLayout(PrintAttributes oldAttributes, PrintAttributes newAttributes, CancellationSignal cancellationSignal,
		                 LayoutResultCallback callback,
		                 Bundle metadata) {
		                 
	myPdfDocument = new PrintedPdfDocument(context, newAttributes); //创建可打印PDF文档对象
		    
	pageHeight = 
                newAttributes.getMediaSize().getHeightMils()/1000 * 72; //设置尺寸
	pageWidth = 
                newAttributes.getMediaSize().getWidthMils()/1000 * 72;
		    
	if (cancellationSignal.isCanceled() ) {
		callback.onLayoutCancelled();
		return;
	}
		    
	if (totalpages > 0) {
	   PrintDocumentInfo.Builder builder = new PrintDocumentInfo
		  .Builder("print_output.pdf") 
		  .setContentType(PrintDocumentInfo.CONTENT_TYPE_DOCUMENT)
		  .setPageCount(totalpages);  //构建文档配置信息
		                
	   PrintDocumentInfo info = builder.build();
	   callback.onLayoutFinished(info, true);
	 } else {
	   callback.onLayoutFailed("Page count is zero.");
	 }
	}
		
		
	@Override
	public void onWrite(final PageRange[] pageRanges,final ParcelFileDescriptor destination,final CancellationSignal cancellationSignal,
		              final WriteResultCallback callback) {
		              
		for (int i = 0; i < totalpages; i++) {
		if (pageInRange(pageRanges, i)) //保证页码正确
	   	{
		     PageInfo newPage = new PageInfo.Builder(pageWidth, 
                         pageHeight, i).create();
		    	
		     PdfDocument.Page page = 
                          myPdfDocument.startPage(newPage);  //创建新页面

		     if (cancellationSignal.isCanceled()) {  //取消信号
			  callback.onWriteCancelled();
			  myPdfDocument.close();
			  myPdfDocument = null;
			  return;
		     }
		     drawPage(page, i);  //将内容绘制到页面Canvas上
		     myPdfDocument.finishPage(page);  
		}
	}
	    
	try {
		myPdfDocument.writeTo(new FileOutputStream(
		            destination.getFileDescriptor()));
	} catch (IOException e) {
		callback.onWriteFailed(e.toString());
		return;
	} finally {
		myPdfDocument.close();
		myPdfDocument = null;
	}

	callback.onWriteFinished(pageRanges);              
	}

	private boolean pageInRange(PageRange[] pageRanges, int page)
	{
		for (int i = 0; i<pageRanges.length; i++)
		{
			if ((page >= pageRanges[i].getStart()) && 
                    	                 (page <= pageRanges[i].getEnd()))
				return true;
		}
		return false;
	}
	//页面绘制(渲染)
	private void drawPage(PdfDocument.Page page, 
                              int pagenumber) {
		    Canvas canvas = page.getCanvas();
                    //这里是页码。页码不能从0开始
		    pagenumber++;
		    
		    int titleBaseLine = 72;
		    int leftMargin = 54;

		    Paint paint = new Paint();
		    paint.setColor(Color.BLACK);
		    paint.setTextSize(40);
		    canvas.drawText(
                     "Test Print Document Page " + pagenumber,
                                                   leftMargin,
                                                   titleBaseLine, 
                                                   paint);

		    paint.setTextSize(14);
		    canvas.drawText("Android PDF 文档打印", leftMargin, titleBaseLine + 35, paint);

		    if (pagenumber % 2 == 0)
		    		paint.setColor(Color.RED);
		    else
		    	paint.setColor(Color.GREEN);
		    
		    PageInfo pageInfo = page.getInfo();
		    
		    
		    canvas.drawCircle(pageInfo.getPageWidth()/2,
                                     pageInfo.getPageHeight()/2, 
                                     150, 
                                     paint); 
		}
}
.


转载于:https://my.oschina.net/ososchina/blog/636397

相关文章:

  • java核心基础之代理机制详解(静态代理、动态代理:JDK、CGlib)
  • Spring事务管理详解(传播属性、隔离级别)
  • 5分钟学会使用Less预编译器
  • RabbitMQ学习系列(一):RabbitMQ的了解安装和使用
  • RabbitMQ学习系列(二):简单队列详解
  • spring学习笔记(4)依赖注入详解
  • RabbitMQ学习系列(三):工作队列详解
  • RabbitMQ学习系列(四):发布-订阅模型详解
  • Android进阶学习
  • RabbitMQ学习系列(五):routing路由模式和Topic主题模式
  • RabbitMQ学习系列(六):RabbitMQ消息确认机制
  • cisco 交换机自动备份配置
  • 应届毕业生因为疫情休息在家,可以通过哪些途径提高自己?
  • APP产品交互设计分析总结(不断更新中...)
  • 以SpringBoot作为后台实践ajax异步刷新
  • SegmentFault for Android 3.0 发布
  • [译]Python中的类属性与实例属性的区别
  • 《Java8实战》-第四章读书笔记(引入流Stream)
  • ES6--对象的扩展
  • express如何解决request entity too large问题
  • in typeof instanceof ===这些运算符有什么作用
  • learning koa2.x
  • miaov-React 最佳入门
  • Vue官网教程学习过程中值得记录的一些事情
  • 表单中readonly的input等标签,禁止光标进入(focus)的几种方式
  • 罗辑思维在全链路压测方面的实践和工作笔记
  • 入职第二天:使用koa搭建node server是种怎样的体验
  • 腾讯大梁:DevOps最后一棒,有效构建海量运营的持续反馈能力
  • 网页视频流m3u8/ts视频下载
  • 一加3T解锁OEM、刷入TWRP、第三方ROM以及ROOT
  • 一起参Ember.js讨论、问答社区。
  • 用jQuery怎么做到前后端分离
  • Java总结 - String - 这篇请使劲喷我
  • ​iOS实时查看App运行日志
  • ![CDATA[ ]] 是什么东东
  • # Redis 入门到精通(八)-- 服务器配置-redis.conf配置与高级数据类型
  • #APPINVENTOR学习记录
  • (01)ORB-SLAM2源码无死角解析-(56) 闭环线程→计算Sim3:理论推导(1)求解s,t
  • (1) caustics\
  • (2)STM32单片机上位机
  • (7)svelte 教程: Props(属性)
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (C++17) optional的使用
  • (java)关于Thread的挂起和恢复
  • (Redis使用系列) SpringBoot中Redis的RedisConfig 二
  • (web自动化测试+python)1
  • (附源码)计算机毕业设计高校学生选课系统
  • (三)Kafka离线安装 - ZooKeeper开机自启
  • (四)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (原創) 系統分析和系統設計有什麼差別? (OO)
  • (转)ObjectiveC 深浅拷贝学习
  • (转)利用PHP的debug_backtrace函数,实现PHP文件权限管理、动态加载 【反射】...
  • ./mysql.server: 没有那个文件或目录_Linux下安装MySQL出现“ls: /var/lib/mysql/*.pid: 没有那个文件或目录”...
  • .bashrc在哪里,alias妙用
  • .bat批处理(一):@echo off