7

I want to create a PDF of "full page" of the activity. The view contains a RecyclerView with many items.

I can take a full dimensions of my Recyclerview but the file is drawed only of the current view. This is my code:

    public void tela (){ // create a new document
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)

    {
        PdfDocument document = new PdfDocument();

        getScreenshotFromRecyclerView(mRecyclerView);
        content = mRecyclerView;
        content.setBackgroundColor(Color.parseColor("#303030"));


        PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(wil,
                height, 1).create();

    // create a new page from the PageInfo
        PdfDocument.Page page = document.startPage(pageInfo);

    // repaint the user's text into the page
        content.draw(page.getCanvas());

    // do final processing of the page
        document.finishPage(page);

    // saving pdf document to sdcard
        SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy - HH-mm-ss",Locale.getDefault());
        String pdfName = "Revisões_"
                + sdf.format(Calendar.getInstance().getTime()) + ".pdf";

    // all created files will be saved at path /sdcard/PDFDemo_AndroidSRC/
        File outputFile = new File(Environment.getExternalStorageDirectory().getPath(), pdfName);

        try {
            outputFile.createNewFile();
            OutputStream out = new FileOutputStream(outputFile);
            document.writeTo(out);
            document.close();
            out.close();
            Toast.makeText(this,"PDF gerado com sucesso",Toast.LENGTH_SHORT).show();
            Log.i("Gerou", "pdf");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

// getting the limits

    public void getScreenshotFromRecyclerView(RecyclerView view) {
    RecyclerView.Adapter adapter = view.getAdapter();
    if (adapter != null) {
        int size = adapter.getItemCount();

        for (int i = 0; i < size; i++) {
            RecyclerView.ViewHolder holder = adapter.createViewHolder(view, adapter.getItemViewType(i));
            adapter.onBindViewHolder(holder, i);
            holder.itemView.measure(View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.EXACTLY),
                    View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
            holder.itemView.layout(0, 0, holder.itemView.getMeasuredWidth(), holder.itemView.getMeasuredHeight());
            height += holder.itemView.getMeasuredHeight();
        }
        wil=view.getMeasuredWidth();


    }
}

The result is this:
enter image description here

Can I create the pdf with the all values of my Recyclerview?

Thanks.

Karen Forde
  • 1,117
  • 8
  • 20
Rafael
  • 79
  • 1
  • 4

2 Answers2

3

I implemented a helper class to handle image saving to PDF. In the method saveImageToPDF() I pass:

  • a TabLayout, which is above my recyclerView
  • the Bitmap of the recyclerView
  • the Context

to get the recyclerView Bitmap I used this Take a screenshot of RecyclerView in FULL length

public class PDFHelper {

    private File mFolder;
    private File mFile;
    private Context mContext;

    public PDFHelper(File folder, Context context) {

        this.mContext = context;
        this.mFolder = folder;

        if(!mFolder.exists())
            mFolder.mkdirs();
    }

    public void saveImageToPDF(View title, Bitmap bitmap, String filename) {

        mFile = new File(mFolder, filename + ".pdf");
        if (!mFile.exists()) {
            int height = title.getHeight() + bitmap.getHeight();
            PdfDocument document = new PdfDocument();
            PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(bitmap.getWidth(), height, 1).create();
            PdfDocument.Page page = document.startPage(pageInfo);
            Canvas canvas = page.getCanvas();
            title.draw(canvas);

            canvas.drawBitmap(bitmap, null, new Rect(0, title.getHeight(), bitmap.getWidth(),bitmap.getHeight()), null);

            document.finishPage(page);

            try {
                mFile.createNewFile();
                OutputStream out = new FileOutputStream(mFile);
                document.writeTo(out);
                document.close();
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}
Community
  • 1
  • 1
0

I have found a more simpler way to do it. I am not sure if my code is clean or is this the right way to do it. I had a recycler view with variable size. I wanted to print the whole length of the recycler view in pdf. Also I use IText Pdf just for reference.

Things that I did. Below is the XML file for the single item in the recycler view. Please note that I have given an ID to the card view as I used card view (You can use any that you want as the root, LinearLayout or RelativeLayout etc.)android:id="@+id/preview_order_list_card_root"

    <?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/preview_order_list_card_root"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="5dp"
    android:layout_marginBottom="5dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="5dp">

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <ImageView
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:layout_gravity="center_horizontal"
                    android:src="@drawable/car"/>

                <TextView
                    android:layout_width="1dp"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:background="@android:color/darker_gray"
                    android:text="12"/>

                <TextView
                    android:id="@+id/preview_car_name"
                    android:layout_width="90dp"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginTop="7dp"
                    android:gravity="center"
                    android:textSize="20sp"
                    android:textStyle="bold"/>

                <TextView
                    android:id="@+id/preview_car_model"
                    android:layout_width="90dp"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:gravity="center"/>

            </LinearLayout>

            <TextView
                android:layout_width="1dp"
                android:layout_height="match_parent"
                android:layout_marginLeft="5dp"
                android:layout_marginRight="5dp"
                android:background="@android:color/darker_gray"/>

            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/preview_part_name"
                    android:layout_width="100dp"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginTop="7dp"
                    android:gravity="center"
                    android:textSize="20sp"
                    android:textStyle="bold"/>

                <TextView
                    android:id="@+id/preview_part_model"
                    android:layout_width="100dp"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginBottom="7dp"
                    android:gravity="center"/>

                <TextView
                    android:layout_width="1dp"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:background="@android:color/darker_gray"
                    android:text="12"/>

                <ImageView
                    android:layout_width="50dp"
                    android:layout_height="50dp"
                    android:layout_gravity="center_horizontal"
                    android:src="@drawable/car_part"/>

            </LinearLayout>

            <TextView
                android:layout_width="1dp"
                android:layout_height="match_parent"
                android:layout_marginLeft="5dp"
                android:background="@android:color/darker_gray"/>

            <LinearLayout
                android:layout_width="70dp"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginLeft="5dp"
                android:orientation="vertical">

                <TextView
                    android:id="@+id/preview_quantity"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="@android:color/holo_green_light"
                    android:gravity="center"
                    android:textSize="25sp"
                    android:layout_gravity="center"/>

                <TextView
                    android:id="@+id/preview_quantity_bucket"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginTop="15dp"
                    android:gravity="center"/>

            </LinearLayout>

        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="bottom"
            android:layout_margin="15dp"
            android:orientation="vertical">

            <TextView
                android:id="@+id/preview_extra_info"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_centerVertical="true"
                android:gravity="center"/>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:layout_marginTop="15dp">

                <TextView
                    android:id="@+id/preview_ordered_from"
                    android:layout_width="100dp"
                    android:layout_height="wrap_content"
                    android:textColor="@android:color/holo_red_light"/>

                <TextView
                    android:id="@+id/preview_list_price"
                    android:layout_width="100dp"
                    android:layout_height="wrap_content"
                    android:gravity="center"/>

                <TextView
                    android:id="@+id/preview_list_less"
                    android:layout_width="80dp"
                    android:layout_height="wrap_content"
                    android:gravity="right"/>

            </LinearLayout>

        </LinearLayout>

    </LinearLayout>

</android.support.v7.widget.CardView>

Now in your adapter just create an arraylist with getters and setters that will save the card view object when ever it calls onBindViewHolder is called as below.

private static ArrayList<CardView> cardViewArrayList = new ArrayList<>();

@Override
    public void onBindViewHolder(final PreviewOrderAdapter.MyViewHolder holder, int position)
    {
        OrderItemDetailsModel orderItemDetailsModel = namesArrList.get(position);
        holder.orderedFrom.setText(orderItemDetailsModel.getOrderedFrom());
        holder.listPrice.setText(orderItemDetailsModel.getListPrice());
        holder.listLess.setText(orderItemDetailsModel.getListLess());

        // ADDING THE CARD VIEW OBJECT IN THE ARRAYLIST
        addCardView(holder.cardView);
    }

    @Override
    public int getItemCount()
    {
        return namesArrList.size();
    }

    private static void addCardView(CardView cardView)
    {
        cardViewArrayList.add(cardView);
    }

    public static ArrayList<CardView> getCardViewList()
    {
        return cardViewArrayList;
    }

Now finally, while printing the recycler views do this.

//Getting the card view array list from the adapter above
ArrayList<CardView> cardViewArrayList = adapter.getCardViewList();
                for (int i = 0; i < cardViewArrayList.size(); i++)
                {
                    // Iterate till the last of the array list and add each view individually to the document.
                    addContent(document, cardViewArrayList.get(i));
                }

//Adding the content to the document
private void addContent(Document document, View view)
            throws DocumentException
    {
        try
        {
            view.buildDrawingCache();

            Bitmap bmp = view.getDrawingCache();

            ByteArrayOutputStream stream = new ByteArrayOutputStream();
            bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
            Image image = Image.getInstance(stream.toByteArray());
            image.scalePercent(70);
            image.setAlignment(Image.MIDDLE);
            document.add(image);
        }
        catch (Exception ex)
        {
            Log.e("TAG-ORDER PRINT ERROR", ex.getMessage());
        }
    }

By this way we dont have to worry about memory leaks due to the large size of the recycler view as we are adding each view separately to the document.

Uzair
  • 91
  • 2
  • 9
  • Some how i managed to work out your idea and it was a successful attempt , but there is a problem . Only visible cells from the recyclerview is showing in saved PDF file . Did you encounter any issue like that . – Nikhil Aug 07 '17 at 08:59