Остановлено ли PdfWriter.getverticalposition () в Itext 7? - PullRequest
0 голосов
/ 01 ноября 2018

Я пытаюсь добавить IBlockElement в конце последней страницы в версии Itext 7 мой подход

  1. После записи всех элементов в pdf документ получим вертикальное позиция от автора с writer.getVerticalPosition ()
  2. Рассчитать доступное пространство на текущей странице с помощью bottomMargin в качестве ссылки.
  3. Если пространство меньше требуемого, добавьте еще одну пустую страницу
  4. Создание и вставка контейнера фиксированной высоты с вертикальным выравниванием текста по bottom Добавить содержимое IBlockElement в контейнер

Однако, когда я использую это

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

Я получаю ошибку:

PdfWriter Writer не содержит определения getverticalposition (). Ни один метод getverticalposition () не принимает сначала аргумент типа PdfWriter вам не хватает ссылки на сборку?

Нужно ли менять ссылку на сборку или что-то в этом роде?

ДАТА РЕДАКТИРОВАНИЯ: 10 ноября 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);
        }

    }

Но текст по-прежнему перекрывается

1 Ответ

0 голосов
/ 05 ноября 2018

iText7 по-прежнему позволяет вам получить аналог текущей вертикальной позиции, но, как отметил @mkl в своем комментарии, в этой концепции есть много нюансов, поскольку iText7 поддерживает гораздо более сложные стратегии компоновки.

Как правило, при переходе с iText5 на iText7 вы должны стараться мыслить «нестандартно» - есть множество вещей, которые вы можете сделать намного проще с iText7, включая ваш пример использования добавления контента внизу последней страницы.

Вы можете использовать аналог iText7 абсолютного позиционирования CSS, чтобы добавить контент внизу. Для этого необходимо указать свойство position, а также смещение bottom. По-прежнему нет причудливого публичного API для этого, потому что функциональность все еще находится в постоянном улучшении, но вы можете сделать это, установив необходимые свойства вручную. Все, что вам нужно сделать, это добавить эти строки:

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

Чтобы продемонстрировать результат, давайте сначала добавим некоторый контент, а затем элемент блока в конец последней страницы.

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 (последняя страница), которая точно соответствует вашему описанию:

result

UPD: Данный алгоритм был обновлен и теперь содержит логику вставки новой страницы для содержимого внизу страницы, если содержимое внизу будет перекрываться с существующим содержимым, если страница не была был вставлен. Чтобы добиться того же поведения, вам понадобится небольшая модификация приведенного выше кода: вместо установки свойств позиционирования с помощью setProperty давайте реализуем наш собственный элемент и соответствующий модуль рендеринга и поместим ваш блочный элемент в эту реализацию. Теперь мы добавим наш элемент следующим образом:

document.add(new BottomBlockElement(glueToBottom));

Реализации просты - просто переместите элемент вниз, между его разметкой и рисованием. Это немного многословно в коде, но все еще довольно ясно:

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

Теперь наша основная часть выглядит так:

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

И результатом является последняя страница, содержащая только нижний блок, если на предыдущей не хватает места:

Overflowing last block if there is not enough space

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...