PdfWriter.getverticalposition()在Itext 7中停止了吗? [英] Is the PdfWriter.getverticalposition() stopped in Itext 7?

查看:197
本文介绍了PdfWriter.getverticalposition()在Itext 7中停止了吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在Itext 7版本的最后一页末尾添加IBlockElement 我的方法是

I am trying to add a IBlockElement at the end of the last page in the Itext 7 version my approach is

  1. 将所有元素写入pdf文档后,获得垂直 使用writer.getVerticalPosition()从作者的位置
  2. 通过使用 bottomMargin作为参考.
  3. 如果空间小于所需空间,请添加另一个空白页
  4. 创建并插入一个高度固定的容器,其文本垂直对齐 底部将IBlockElement内容添加到容器中
  1. After writing all the elements to the pdf document get the vertical position from the writer with writer.getVerticalPosition()
  2. Calculate the available space on the current page by using the bottomMargin as a reference.
  3. If space is less than the space required then add another blank page
  4. Create and insert a container of fixed height with text vertical alignment to bottom Add IBlockElement content to the container

但是我何时使用它

var PdfWriter= new PdfWriter(memoryStream, writerProperties)
PdfWriter.getverticalposition()

我遇到错误:

PdfWriter编写器不包含的定义 getverticalposition().没有方法getverticalposition()首先接受 PdfWriter类型的参数是否缺少程序集引用?

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?

编辑日期:2018年11月10日

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);
        }

    }

但是文本仍然重叠

推荐答案

iText7仍然允许您获得当前垂直位置的类似物,但是正如@mkl在他的评论中指出的那样,由于iText7支持,此概念有很多细微差别.更复杂的布局策略.

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.

通常,从iText5迁移到iText7时,有时您应该尝试开箱即用-使用iText7可以做很多事情,包括在最后一页底部添加内容的用例.

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.

您可以使用CSS绝对定位的iText7类似物在底部添加内容.为此,您必须指定position属性以及bottom偏移量.由于该功能仍在不断改进中,因此仍然没有花哨的公共API可以执行此操作,但是您可以通过手动设置必要的属性来做到这一点.您需要做的就是添加以下行:

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 as bottom 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:

glueToBottom.setProperty(Property.POSITION, LayoutPosition.ABSOLUTE);
glueToBottom.setProperty(Property.BOTTOM, 0);

为演示结果,让我们先添加一些内容,然后在最后一页的末尾添加块元素.

To demonstrate the result, let's add some content first and then the block element to the end of the last page.

Document document = new Document(pdfDocument);

for (int i = 0; i < 40; i++) {
    document.add(new Paragraph("Hello " + i));
}

IBlockElement glueToBottom = new Paragraph("Hi, I am the bottom content")
        .setFontSize(25)
        .setWidth(UnitValue.createPercentValue(100))
        .setBackgroundColor(ColorConstants.RED)
        .setTextAlignment(TextAlignment.CENTER);
glueToBottom.setProperty(Property.POSITION, LayoutPosition.ABSOLUTE);
glueToBottom.setProperty(Property.BOTTOM, 0);

document.add(glueToBottom);

document.close();

您将在第2页(最后一页)看到与您的描述完全相符的内容:

You will get something like this at page 2 (last page), which matches your description exactly:

UPD::相关算法已更新,现在包含以下逻辑:如果页面底部的内容与现有内容重叠,则为页面底部的内容插入新页面尚未插入.为了实现相同的行为,您需要对上面的代码进行一些修改:代替通过setProperty设置定位属性,让我们实现自己的元素和相应的渲染器,并将您的block元素包装到该实现中.现在,我们将添加元素,如下所示:

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:

document.add(new BottomBlockElement(glueToBottom));

实现很简单-只需在布局和绘制之间将元素移到底部即可.这在代码中有点冗长,但仍然很清楚:

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:

private static class BottomBlockElement extends Div {
    public BottomBlockElement(IBlockElement wrapping) {
        super();
        add(wrapping);
        setKeepTogether(true);
    }

    @Override
    protected IRenderer makeNewRenderer() {
        return new BottomBlockRenderer(this);
    }
}

private static class BottomBlockRenderer extends DivRenderer {
    public BottomBlockRenderer(BottomBlockElement modelElement) {
        super(modelElement);
    }

    @Override
    public LayoutResult layout(LayoutContext layoutContext) {
        LayoutResult result = super.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;
        }
    }

    @Override
    public IRenderer getNextRenderer() {
        return new BottomBlockRenderer((BottomBlockElement) modelElement);
    }
}

现在我们的主要部分是这样的:

Now our main part looks like this:

Document document = new Document(pdfDocument);

for (int i = 0; i < 58; i++) {
    document.add(new Paragraph("Hello " + i));
}

IBlockElement glueToBottom = new Paragraph("Hi, I am the bottom content")
        .setFontSize(25)
        .setWidth(UnitValue.createPercentValue(100))
        .setBorder(new SolidBorder(ColorConstants.RED, 1))
        .setTextAlignment(TextAlignment.CENTER);

document.add(new BottomBlockElement(glueToBottom));

document.close();

如果前一个页面没有足够的空间,则结果是最后一个页面仅包含最下面的块:

And the result is the last page containing only the bottom block if the previous one does not have enough space:

这篇关于PdfWriter.getverticalposition()在Itext 7中停止了吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆