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:
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:
table.getDefaultCell().setFixedHeight(112f)
Result with short text:
Result with long text:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With