如何打印任意一个界面

最近做一个需要将APP里的一个报告通过打印机打印出来的项目,我是小白,在网上看了很多有关打印机的程序,还是一头雾水,最后发现一个简单的方法(虽然有点甩锅的嫌疑),能实现打印的目的。

首先说一下思路,因为需要打印的报告是在程序里生成的(其实就是一个布局页面,只是需要往控件里填数据),如果把数据全传给网络打印机的话,非常繁琐。何不直接传一个图片或者文件。于是我就把整个页面保存为图片存在SD卡文件夹中。然后将图片生成PDF文件,再通过WPS或者Office打开并用自带的打印功能进行打印(这就是把打印的事甩给了第三方)。还有就是单独的图片其实也是可以打印的(手机的功能真是强大),不需要生成PDF,但是考虑到需要打印多个界面时,一张张打实在是费事,而且打印效果也不是很理想,因此生成PDF会好很多。今天生成PDF成功了,因此把方法分享并保存下来,以便以后回顾。下面是我的简单的Demo。

首先,生成PDF我用的是Itext(虽然网上有的说并不好用,但是只是将图片生成PDF的话,还是这种方法简单。),添加Itext的依赖,可以在http://mvnrepository.com/artifact/com.itextpdf/itextpdf这里找到,各个版本都有,找到Gradle方式的依赖,将compile group: 'com.itextpdf', name: 'itextpdf', version: '5.5.13'添加到app下的build.gradle中,5.5.13是目前的最新版本。值得注意的是gradle版本到4.1以后不再用compile添加,而用implementation。

然后申请权限

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>

布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/zong"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#ffffff"
    >
    <ImageView
        android:id="@+id/back_ground"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

    <TextView
        android:id="@+id/text1"
        android:text="aaaaaa"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />
    <Button
        android:id="@+id/take_photo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="100dp"
        android:text="生成PDF"/>

</RelativeLayout>

布局很简单,其中ImageView的背景图片是在程序中添加的,主要是当时不知是否是保存初始页面,还是保存更改了信息后的页面。因此来区分验证一下。

其中有几个重要的方法

将要保存的View生成Bitmap对象。

private Bitmap getBitmap(View view){
    view.setDrawingCacheEnabled(true);
    view.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
            View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
    view.layout(0, 0, view.getMeasuredWidth(),view.getMeasuredHeight() );
    Bitmap bitmap=view.getDrawingCache();
    return bitmap;
}

随机生成一个文件名。

private static String generateFileName() {
    return UUID.randomUUID().toString();
}

将Bitmap对象以jpg格式保存在SD卡中,并返回保存的路径,SD_PATH和IN_PATH是随便定义的文件夹。

private   String saveBitmap(Context context, Bitmap mBitmap) {
    String savePath;
    File filePic;
    if (Environment.getExternalStorageState().equals(
            Environment.MEDIA_MOUNTED)) {
        savePath = SD_PATH;
    } else {
        savePath = context.getApplicationContext().getFilesDir()
                .getAbsolutePath()
                + IN_PATH;
    }
    try {
        filePic = new File(savePath + generateFileName() + ".jpg");
        if (!filePic.exists()) {
            filePic.getParentFile().mkdirs();
            filePic.createNewFile();
        }
        FileOutputStream fos = new FileOutputStream(filePic);
        mBitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
        fos.flush();
        fos.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
        return null;
    }
    imagepath = filePic.getAbsolutePath();
    Log.d("sssssssss","---------"+imagepath);
    return imagepath;
}

将图片生成.pdf格式文件,其中imagepath是要被生成的图片的路径,pdfpath是生成的pdf文件被保存的路径。

public boolean imageToPDF(String imagepath,String pdfpath)throws IOException{
    File file = new File(imagepath);
    if (file.exists()){
        Document document = new Document();
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(pdfpath);
            PdfWriter.getInstance(document,fos);
            // 添加PDF文档的某些信息,比如作者,主题等等
            document.addAuthor("arui");
            document.addSubject("test pdf.");
            // 设置文档的大小
            document.setPageSize(PageSize.A4);
            // 打开文档
            document.open();
           // 写入一段文字
            //document.add(new Paragraph("JUST TEST ..."));
            Image image = Image.getInstance(imagepath);
            float imageHeight=image.getScaledHeight();
            float imageWidth=image.getScaledWidth();
            int i=0;
            while(imageHeight>500||imageWidth>500) {
                image.scalePercent(100 - i);
                i++;
                imageHeight = image.getScaledHeight();
                imageWidth = image.getScaledWidth();
                System.out.println("imageHeight->" + imageHeight);
                System.out.println("imageWidth->" + imageWidth);
            }
            image.setAlignment(Image.ALIGN_CENTER);
            //     //设置图片的绝对位置
             //image.setAbsolutePosition(0, 0);
             //image.scaleAbsolute(500, 400);
            // 插入一个图片
            document.add(image);
        }catch (DocumentException dc){
            dc.printStackTrace();

        }catch (IOException ioe){
            ioe.printStackTrace();

        }
        document.close();
        fos.flush();
        fos.close();
        Toast.makeText(this,"生成PDF成功",Toast.LENGTH_SHORT).show();
        return true;
    }else {
        return false;
    }
}

然后就是调用对应的方法即可,就可以将页面(包括任意一块布局)在制定文件夹中生成pdf文件,记得调用imageToPDFS方法时记得抛异常就行了,我是新手,还在学习中,哪里有错欢迎大佬们指出,共同进步。

效果图

如何打印任意一个界面