I am trying to add a IBlockElement at the end of the last page in the Itext 7 version my approach is
- After writing all the elements to the pdf document get the vertical position from the writer with writer.getVerticalPosition()
- Calculate the available space on the current page by using the bottomMargin as a reference.
- If space is less than the space required then add another blank page
- Create and insert a container of fixed height with text vertical alignment to bottom Add IBlockElement content to the container
However when I am using it
var PdfWriter= new PdfWriter(memoryStream, writerProperties)
PdfWriter.getverticalposition()
I am getting error:
PdfWriter writer does not contain a definition of getverticalposition(). No method getverticalposition() accept first argument of type PdfWriter are you missing assembly reference?
Do I have to change the assembly reference or something?
EDIT DATE: 10-Nov-2018
private class BottomBlockElement : Div
{
public BottomBlockElement(IBlockElement wrapping)
{
base.SetKeepTogether(true);
base.Add(wrapping);
//add(wrapping);
//setKeepTogether(true);
}
override protected IRenderer MakeNewRenderer()
{
return new BottomBlockRenderer(this);
}
}
private class BottomBlockRenderer : DivRenderer
{
public BottomBlockRenderer(BottomBlockElement modelElement) : base(modelElement)
{
}
override public LayoutResult Layout(LayoutContext layoutContext)
{
LayoutResult result = base.Layout(layoutContext);
if (result.GetStatus() == LayoutResult.FULL)
{
float leftoverHeight = result.GetOccupiedArea().GetBBox().GetBottom() - layoutContext.GetArea().GetBBox().GetBottom();
Move(0, -leftoverHeight);
return new LayoutResult(result.GetStatus(), layoutContext.GetArea(), result.GetSplitRenderer(), result.GetOverflowRenderer());
}
else
{
return result;
}
}
public override IRenderer GetNextRenderer()
{
return new BottomBlockRenderer((BottomBlockElement)modelElement);
}
}
But still the text is overlapping
iText7 still allows you to get analogue of current vertical position, but as @mkl noted in his comment, there are are lot of nuances with this concept because iText7 support much more complex layout strategies.
In general you should try to think out of the box sometimes when migrating from iText5 to iText7 - there are a ton of things you can do much easier with iText7, including your use case of adding content to the bottom of last page.
You can use iText7 analogue of CSS absolute positioning to add content to the bottom. To do that, you have to specify
position
property as well asbottom
offset. There is still no fancy public API to do that because the functionality is still under constant improvement, but you can do that with setting necessary properties manually. All you need to do is add these lines:To demonstrate the result, let's add some content first and then the block element to the end of the last page.
You will get something like this at page 2 (last page), which matches your description exactly:
UPD: The algorithm in question was updated and now contains logic of inserting a new page for the content at the bottom of the page if the content at the bottom would overlap with existing content had the page not been inserted. To achieve same behavior you would need a slight modification of the code above: instead of setting positioning properties via
setProperty
let's implement our own element and corresponding renderer and wrap your block element into this implementation. We will add our element now as follows:The implementations are straightforward - just move the element to the bottom between laying it out and drawing. This is a bit verbose in code but still quite clear:
Now our main part looks like this:
And the result is the last page containing only the bottom block if the previous one does not have enough space: