Creating a PDF file using iText from Recyclerview (all elements inside) in Android?

Hi, I tried to create a PDF output file from Recyclerview using the iText library. After hours of struggle, I was able to create a PDF from recylerview.

Below are the classes that I used to create the PDF

Codes from the main class

private void getPrint() { ArrayList<View> viewArrayList = mAdapter.getPrintView(); // A function from Adapter class which returns ArrayList of VIEWS Document document = new Document(PageSize.A4); final File file = new File(getStorageDir("PDF"), "print.pdf"); try { PdfWriter.getInstance(document, new FileOutputStream(file)); } catch (DocumentException | FileNotFoundException e) { e.printStackTrace(); } for (int im = 0; im < viewArrayList.size(); im++) { // Iterate till the last of the array list and add each view individually to the document. try { viewArrayList.get(im).buildDrawingCache(); //Adding the content to the document Bitmap bmp = viewArrayList.get(im).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); if (!document.isOpen()) { document.open(); } document.add(image); } catch (Exception ex) { Log.e("TAG-ORDER PRINT ERROR", ex.getMessage()); } } if (document.isOpen()) { document.close(); } AlertDialog.Builder builder = new AlertDialog.Builder(Index.this); builder.setTitle("Success") .setMessage("PDF File Generated Successfully.") .setIcon(android.R.drawable.ic_dialog_alert) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(file), "application/pdf"); intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); startActivity(intent); } }).show(); } 

RecyclerView generic adapter class

  public class RecyclerAdapter<T, VM extends ViewDataBinding> extends RecyclerView.Adapter<RecyclerAdapter.RecyclerViewHolder> { private final Context context; private ArrayList<T> items; private int layoutId; private RecyclerCallback<VM, T> bindingInterface; private static ArrayList<View> mPrintView = new ArrayList<>(); public RecyclerAdapter(Context context, ArrayList<T> items, int layoutId, RecyclerCallback<VM, T> bindingInterface) { this.items = items; this.context = context; this.layoutId = layoutId; this.bindingInterface = bindingInterface; } public class RecyclerViewHolder extends RecyclerView.ViewHolder { VM binding; public RecyclerViewHolder(View view) { super(view); binding = DataBindingUtil.bind(view); } public void bindData(T model) { bindingInterface.bindData(binding, model); binding.executePendingBindings(); } } @Override public RecyclerViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { View v = LayoutInflater.from(parent.getContext()) .inflate(layoutId, parent, false); return new RecyclerViewHolder(v); } @Override public void onBindViewHolder(RecyclerAdapter.RecyclerViewHolder holder, int position) { T item = items.get(position); Log.e("PRINT ", holder.binding.getRoot().getId() + ""); mPrintView.add(holder.binding.getRoot()); holder.bindData(item); } @Override public int getItemCount() { if (items == null) { return 0; } return items.size(); } public static ArrayList<View> getPrintView() { return mPrintView; } 

}

I am using an Arraylist called mPrintView to save views inside RecylerView. The problem arises when the USER scrolls UP and DOWM repeatedly when the data inside the ArrayList is duplicated.

Below are images of the results that I received after converting PDF

Case 1: when the user scrolls only one time

enter image description here

Case 2: when the user scrolls UP and DOWN several times

enter image description here

In the above image, you may notice that Apple is duplicating

Any help is appreciated.

+1
java android pdf itext
source share
2 answers

After hours of traces and mistakes, I found the answer. I am sharing code snippets as this may be useful for some other

  public void generatePDF(RecyclerView view) { RecyclerView.Adapter adapter = view.getAdapter(); Bitmap bigBitmap = null; if (adapter != null) { int size = adapter.getItemCount(); int height = 0; Paint paint = new Paint(); int iHeight = 0; final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); // Use 1/8th of the available memory for this memory cache. final int cacheSize = maxMemory / 8; LruCache<String, Bitmap> bitmaCache = new LruCache<>(cacheSize); 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()); holder.itemView.setDrawingCacheEnabled(true); holder.itemView.buildDrawingCache(); Bitmap drawingCache = holder.itemView.getDrawingCache(); if (drawingCache != null) { bitmaCache.put(String.valueOf(i), drawingCache); } height += holder.itemView.getMeasuredHeight(); } bigBitmap = Bitmap.createBitmap(view.getMeasuredWidth(), height, Bitmap.Config.ARGB_8888); Canvas bigCanvas = new Canvas(bigBitmap); bigCanvas.drawColor(Color.WHITE); Document document = new Document(PageSize.A4); final File file = new File(getStorageDir("PDF"), "print.pdf"); try { PdfWriter.getInstance(document, new FileOutputStream(file)); } catch (DocumentException | FileNotFoundException e) { e.printStackTrace(); } for (int i = 0; i < size; i++) { try { //Adding the content to the document Bitmap bmp = bitmaCache.get(String.valueOf(i)); ByteArrayOutputStream stream = new ByteArrayOutputStream(); bmp.compress(Bitmap.CompressFormat.PNG, 100, stream); Image image = Image.getInstance(stream.toByteArray()); float scaler = ((document.getPageSize().getWidth() - document.leftMargin() - document.rightMargin() - 0) / image.getWidth()) * 100; // 0 means you have no indentation. If you have any, change it. image.scalePercent(scaler); image.setAlignment(com.itextpdf.text.Image.ALIGN_CENTER | com.itextpdf.text.Image.ALIGN_TOP); if (!document.isOpen()) { document.open(); } document.add(image); } catch (Exception ex) { Log.e("TAG-ORDER PRINT ERROR", ex.getMessage()); } } if (document.isOpen()) { document.close(); } // Set on UI Thread runOnUiThread(new Runnable() { @Override public void run() { AlertDialog.Builder builder = new AlertDialog.Builder(Index.this); builder.setTitle("Success") .setMessage("PDF File Generated Successfully.") .setIcon(android.R.drawable.ic_dialog_alert) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.fromFile(file), "application/pdf"); intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); startActivity(intent); } }).show(); } }); } } 
+1
source share

You saved my day. But I had to change this line:

 image.scalePercent(70); image.setAlignment(Image.MIDDLE); 

with this:

 float scaler = ((document.getPageSize().getWidth() - document.leftMargin() - document.rightMargin() - 0) / image.getWidth()) * 100; // 0 means you have no indentation. If you have any, change it. image.scalePercent(scaler); image.setAlignment(com.itextpdf.text.Image.ALIGN_CENTER | com.itextpdf.text.Image.ALIGN_TOP); 

Many thanks

+1
source share

All Articles