Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Create a rectangle, add paragraph inside that and adjust the height of the rectangle according to the text using iText

Tags:

android

pdf

itext

I am able to create a rectangle and add paragraph and image inside it. The rectangle's width is also fine but I just want to set the height of the rectangle according to the text in paragraph. Also I wanted to add the data inside rectangle in a particular manner that is why I have created table inside it. So how to make the table to fill the entire rectangle. Can anybody please help me with this?

        PdfContentByte cb = writer.getDirectContent();

        Rectangle rect = new Rectangle(kBorderInset, document.getPageSize().getHeight()-kPageDisclaimerY,
                document.getPageSize().getWidth()-2 * kBorderInset,700f);
        cb.rectangle(rect);
        cb.stroke();

        rect.setBorder(Rectangle.BOX);
        rect.setBorderWidth(1);
        rect.setBorderColor(BaseColor.BLACK);
        cb.rectangle(rect);

        ColumnText ct = new ColumnText(cb);
        ct.setSimpleColumn(rect);
        ct.addElement(createTable1(auditBundle, context));
        ct.go();

Create table code

       private static PdfPTable createTable1(AuditBundle auditBundle, Context context) throws 
       DocumentException {
           PdfPTable table = new PdfPTable(3);
           table.setWidthPercentage(100);
           table.getDefaultCell().setUseAscender(true);
           table.getDefaultCell().setUseDescender(true);
           table.getDefaultCell().setFixedHeight(112f);
           table.setWidths(new int[]{1, 2, 1});

    float fntSize, lineSpacing;
    fntSize = 20f;
    lineSpacing = 12f;
    Paragraph paragraph = new Paragraph();
    paragraph.add(new Phrase(lineSpacing,auditBundle.getAudit().auditName,
            FontFactory.getFont(FontFactory.HELVETICA, fntSize)));
    paragraph.setAlignment(Element.ALIGN_LEFT | Element.ALIGN_CENTER);
    paragraph.setPaddingTop(30);
    PdfPCell cell = new PdfPCell();
    cell.addElement(paragraph);
    cell.setBackgroundColor(BaseColor.LIGHT_GRAY);
    cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
    table.addCell("");
    table.addCell(cell);

    Drawable d = context.getDrawable(R.drawable.ic_action_device_access_camera); // the drawable (Captain Obvious, to the rescue!!!)
    assert d != null;
    Bitmap bitmap = ((BitmapDrawable)d).getBitmap();
    ByteArrayOutputStream stream = new ByteArrayOutputStream();
    bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
    byte[] bitmapdata = stream.toByteArray();

    PdfPCell cellImg = new PdfPCell();
    try {
        Image image = Image.getInstance(bitmapdata);
        image.setAlignment(Element.ALIGN_CENTER);
        cellImg.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cellImg.addElement(image);
        cellImg.setBackgroundColor(BaseColor.WHITE);
    } catch (IOException e) {
        e.printStackTrace();
    }
    table.addCell(cellImg);
    return table;
}

Currently it is looking like this: enter image description here

like image 591
shruity Avatar asked May 08 '20 07:05

shruity


1 Answers

If your content is in a table and you want to draw a rectangle around it, the most straightforward way is to use the table border. That eliminates the need to draw an additional rectangle.

If drawing the rectangle separately is required, you could simply add the content and get the resulting vertical position (writer.getVerticalPosition(false)). Then draw the rectangle based on the vertical position before and after adding the content.

Still, the generic problem of determining the area needed to render a piece of content is an interesting one. So I'll reply in the context of the table, as defined in the question, although it's probably not the most useful approach. It can be applied for other types of content and use cases.

First of all, in PDF the coordinates increase from left to right and from bottom to top. The Rectangle constructor you're using is Rectangle(final float lowerleftx, final float lowerlefty, final float upperrightx, final float upperrighty). So lowerlefty should be a smaller number than upperrighty. You can also ignore that, define the Rectangle "upside down" and call Rectangle.normalize().

To determine the vertical space needed to render the content, you can run ColumnText in simulation mode. It will do all the rendering logic without actually writing the content to the PDF document. You can then use the information from that simulation run to tweak the actual rendering in the second stage.

PdfContentByte cb = writer.getDirectContent();

// the initial rectangle defines the max size of the content
Rectangle rect = new Rectangle(10, document.getPageSize().getBottom() + 50,
        document.getPageSize().getWidth() - 2 * 10, document.getPageSize().getTop() - 50);

// flip the rectangle if top and bottom were switched
rect.normalize();

ColumnText ct = new ColumnText(cb);
ct.setSimpleColumn(rect);
ct.addElement(createTable1(auditBundle, context));

// do a simulation run
int result = ct.go(true);

// assume the content fits in the initial rectangle
if (result == ColumnText.NO_MORE_TEXT) {

    // the bottom of the simulated content
    float verticalpos = ct.getYLine();

    // redefine the rectangle based on the simulation
    rect = new Rectangle(10, verticalpos, document.getPageSize().getWidth() - 2 * 10,
            document.getPageSize().getTop() - 50);
    ct.setSimpleColumn(rect);

    // the original content was consumed in the simulation, so add it again
    ct.addElement(createTable1(auditBundle, context));

    // render again
    ct.go(false);

    // draw the rectangle
    rect.setBorder(Rectangle.BOX);
    rect.setBorderWidth(1);
    rect.setBorderColor(BaseColor.RED);
    cb.rectangle(rect);

}

Further changes to the original code:

  • Removed the fixed height of the table cells, so the growing and shrinking of the rectangle can be demonstrated more clearly: removed table.getDefaultCell().setFixedHeight(112f)
  • Removed the table border and changed the rectangle color to red to show the rectangle more clearly.

Result with short text: Result with short text

Result with long text: Result with long text

like image 93
rhens Avatar answered Sep 23 '22 19:09

rhens