Управление маркированными и нумерованными списками в презентациях на Android
Обзор
Aspose.Slides for Android via Java позволяет создавать и форматировать маркированные и нумерованные списки в презентациях PowerPoint и OpenDocument. Элемент списка — это абзац, настройки маркера которого управляются через формат абзаца.
Используйте метод IParagraph.getParagraphFormat для доступа к настройкам списка на уровне абзаца. Основной точкой входа является IParagraphFormat.getBullet, который возвращает объект IBulletFormat. С помощью этого объекта можно задать тип маркера, символ, изображение, цвет, размер, стиль нумерации и начальное число.
В этой статье показано, как:
- создать маркированный список с пользовательским символом
- создать маркер‑картинку
- создать многоуровневый список, задав глубину абзаца
- создать нумерованный список
- просмотреть и изменить форматирование списка в существующей презентации
- прочитать фактические маркеры и номера списков рядом с текстом абзаца
Создание маркированного списка
Чтобы создать маркированный список, добавьте абзацы в ITextFrame и задайте IBulletFormat.setType значение BulletType.Symbol. Затем можно задать IBulletFormat.setChar, IBulletFormat.getColor и IBulletFormat.setHeight для управления внешним видом маркера.
Ниже приведён пример Java‑кода, показывающий, как создать маркированный список на слайде:
import com.aspose.slides.*;
import android.graphics.Color;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(0);
IAutoShape autoShape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 20, 20, 200, 50);
ITextFrame textFrame = autoShape.getTextFrame();
textFrame.getParagraphs().clear();
int bulletColor = Color.rgb(205, 92, 92);
Paragraph paragraph1 = new Paragraph();
paragraph1.getParagraphFormat().getBullet().setType(BulletType.Symbol);
paragraph1.getParagraphFormat().getBullet().setChar('*');
paragraph1.getParagraphFormat().setIndent(15);
paragraph1.getParagraphFormat().getBullet().setBulletHardColor(NullableBool.True);
paragraph1.getParagraphFormat().getBullet().getColor().setColor(bulletColor);
paragraph1.getParagraphFormat().getBullet().setHeight(100);
paragraph1.setText("The first paragraph");
textFrame.getParagraphs().add(paragraph1);
Paragraph paragraph2 = new Paragraph();
paragraph2.getParagraphFormat().getBullet().setType(BulletType.Symbol);
paragraph2.getParagraphFormat().getBullet().setChar('*');
paragraph2.getParagraphFormat().setIndent(15);
paragraph2.getParagraphFormat().getBullet().setBulletHardColor(NullableBool.True);
paragraph2.getParagraphFormat().getBullet().getColor().setColor(bulletColor);
paragraph2.getParagraphFormat().getBullet().setHeight(100);
paragraph2.setText("The second paragraph");
textFrame.getParagraphs().add(paragraph2);
presentation.save("symbol_bullets.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Результат:

Создание нумерованного списка
Используйте нумерованные списки, когда порядок элементов важен. Задайте IBulletFormat.setType значение BulletType.Numbered. Также можно выбрать формат нумерации с помощью IBulletFormat.setNumberedBulletStyle или задать IBulletFormat.setNumberedBulletStartWith, если список должен начинаться с числа, отличного от 1.
Ниже показан Java‑код, создающий нумерованный список на слайде:
import com.aspose.slides.*;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(0);
IAutoShape autoShape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 20, 20, 90, 80);
ITextFrame textFrame = autoShape.getTextFrame();
textFrame.getParagraphs().clear();
Paragraph paragraph1 = new Paragraph();
paragraph1.getParagraphFormat().getBullet().setType(BulletType.Numbered);
paragraph1.setText("Apple");
textFrame.getParagraphs().add(paragraph1);
Paragraph paragraph2 = new Paragraph();
paragraph2.getParagraphFormat().getBullet().setType(BulletType.Numbered);
paragraph2.setText("Orange");
textFrame.getParagraphs().add(paragraph2);
Paragraph paragraph3 = new Paragraph();
paragraph3.getParagraphFormat().getBullet().setType(BulletType.Numbered);
paragraph3.setText("Banana");
textFrame.getParagraphs().add(paragraph3);
presentation.save("numbered_bullets.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Результат:

Создание маркера‑картинки
Aspose.Slides позволяет заменить обычный символ маркера изображением. Маркеры‑картинки лучше всего работают с простыми изображениями, которые остаются читабельными при небольшом размере, например, иконками или небольшими прозрачными PNG‑файлами.
Note
Идеально, если вы планируете заменить обычный символ маркера изображением, выбирать простую графику с прозрачным фоном. Такие изображения хорошо подходят в качестве пользовательских символов маркеров.Чтобы создать маркер‑картинку, добавьте изображение в Presentation.getImages и присвойте полученный объект IPPImage свойству IBulletFormat.getPicture. Перед назначением изображения задайте IBulletFormat.setType значение BulletType.Picture.
Допустим, у нас есть файл image.png:

Ниже показан Java‑код, создающий маркеры‑картинки на слайде:
import com.aspose.slides.*;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(0);
IAutoShape autoShape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 20, 20, 200, 50);
ITextFrame textFrame = autoShape.getTextFrame();
textFrame.getParagraphs().clear();
IPPImage bulletImage = presentation.getImages().addImage(Images.fromFile("image.png"));
Paragraph paragraph1 = new Paragraph();
paragraph1.getParagraphFormat().getBullet().setType(BulletType.Picture);
paragraph1.getParagraphFormat().getBullet().getPicture().setImage(bulletImage);
paragraph1.getParagraphFormat().setIndent(15);
paragraph1.getParagraphFormat().getBullet().setHeight(100);
paragraph1.setText("The first paragraph");
textFrame.getParagraphs().add(paragraph1);
Paragraph paragraph2 = new Paragraph();
paragraph2.getParagraphFormat().getBullet().setType(BulletType.Picture);
paragraph2.getParagraphFormat().getBullet().getPicture().setImage(bulletImage);
paragraph2.getParagraphFormat().setIndent(15);
paragraph2.getParagraphFormat().getBullet().setHeight(100);
paragraph2.setText("The second paragraph");
textFrame.getParagraphs().add(paragraph2);
presentation.save("picture_bullets.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Результат:

Создание многоуровневого списка
Используйте IParagraphFormat.setDepth для размещения элементов списка на разных уровнях. Уровень 0 — верхний уровень, уровень 1 — вложенный под ним и т.д.
Ниже пример Java‑кода, создающего многоуровневый список:
import com.aspose.slides.*;
Presentation presentation = new Presentation();
try {
ISlide slide = presentation.getSlides().get_Item(0);
IAutoShape autoShape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 20, 20, 260, 110);
ITextFrame textFrame = autoShape.getTextFrame();
textFrame.getParagraphs().clear();
Paragraph paragraph1 = new Paragraph();
paragraph1.getParagraphFormat().setDepth((short) 0);
paragraph1.setText("My text - Depth 0");
textFrame.getParagraphs().add(paragraph1);
Paragraph paragraph2 = new Paragraph();
paragraph2.getParagraphFormat().setDepth((short) 1);
paragraph2.setText("My text - Depth 1");
textFrame.getParagraphs().add(paragraph2);
Paragraph paragraph3 = new Paragraph();
paragraph3.getParagraphFormat().setDepth((short) 2);
paragraph3.setText("My text - Depth 2");
textFrame.getParagraphs().add(paragraph3);
Paragraph paragraph4 = new Paragraph();
paragraph4.getParagraphFormat().setDepth((short) 3);
paragraph4.setText("My text - Depth 3");
textFrame.getParagraphs().add(paragraph4);
presentation.save("multilevel_bullets.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Результат:

Изменение существующего списка
Чтобы изменить форматирование списка в существующей презентации, получите целевой абзац и обновите его настройки IParagraphFormat.getBullet. Те же методы, которые использовались для создания списков, можно применять для просмотра или изменения списков, загруженных из файлов PPT, PPTX или ODP.
Ниже Java‑код, меняющий первый абзац в текстовом фрейме на нумерованный стиль списка:
import com.aspose.slides.*;
Presentation presentation = new Presentation("input.pptx");
try {
ISlide slide = presentation.getSlides().get_Item(0);
IAutoShape autoShape = (IAutoShape) slide.getShapes().get_Item(0);
IParagraph paragraph = autoShape.getTextFrame().getParagraphs().get_Item(0);
paragraph.getParagraphFormat().getBullet().setType(BulletType.Numbered);
paragraph.getParagraphFormat().getBullet().setNumberedBulletStyle(NumberedBulletStyle.BulletRomanUCPeriod);
paragraph.getParagraphFormat().getBullet().setNumberedBulletStartWith((short) 1);
paragraph.getParagraphFormat().setMarginLeft(30);
paragraph.getParagraphFormat().setIndent(-20);
presentation.save("updated_list.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Чтение фактических значений маркеров
При извлечении содержимого презентации сохраняйте маркеры списков рядом с текстом абзаца. Вызовите IParagraphFormat.getEffective и получите IParagraphFormatEffectiveData.getBullet для получения эффективного формата маркера. Проверьте его getType перед чтением getActualBulletValue.
Для нумерованных списков различайте три значения:
- getNumberedBulletStyle определяет формат, например арабские цифры с точкой или строчные буквы с точкой.
- getNumberedBulletStartWith указывает начальное число для группы нумерованных абзацев.
- getActualBulletValue возвращает отформатированный маркер конкретного абзаца. Например, второй пункт списка, начинающегося с 5, вернёт
6..
Сохраняйте getDepth у каждого абзаца, чтобы удержать уровень вложения. Фактический маркер не кодирует всю иерархию: вложенный элемент может вернуть c. вместо комбинированного ярлыка вроде 6.c..
Ниже приведён самостоятельный пример, создающий списки, сохраняющий их в презентацию и затем загружающий презентацию для вывода текста каждого абзаца, глубины, типа маркера и фактического значения. Маленький синий маркер‑картинка создаётся из встроенного SVG.
import com.aspose.slides.*;
import android.graphics.Color;
Presentation presentation = new Presentation();
try {
presentation.getSlideSize().setSize(720, 440, SlideSizeScaleType.DoNotScale);
ISlide slide = presentation.getSlides().get_Item(0);
IAutoShape shape = slide.getShapes().addAutoShape(ShapeType.Rectangle, 30, 20, 660, 400);
shape.getFillFormat().setFillType(FillType.NoFill);
shape.getLineFormat().getFillFormat().setFillType(FillType.NoFill);
ITextFrame textFrame = shape.getTextFrame();
textFrame.getParagraphs().clear();
// Создать маркер‑картинку без внешнего файла изображения.
SvgImage svg = new SvgImage("<svg xmlns='http://www.w3.org/2000/svg' width='16' height='16'><rect width='16' height='16' rx='4' fill='#0078D4'/></svg>");
IPPImage bulletImage = presentation.getImages().addImage(svg);
class ListBuilder {
void addParagraph(String text, short depth, byte type, short start, byte style) {
Paragraph paragraph = new Paragraph();
paragraph.setText(text);
IParagraphFormat format = paragraph.getParagraphFormat();
format.setDepth(depth);
format.setMarginLeft(30 + depth * 40);
format.setIndent(-28);
format.setSpaceAfter(8);
format.getDefaultPortionFormat().setFontHeight(22);
format.getDefaultPortionFormat().getFillFormat().setFillType(FillType.Solid);
format.getDefaultPortionFormat().getFillFormat().getSolidFillColor().setColor(Color.BLACK);
format.getBullet().setType(type);
format.getBullet().setBulletHardColor(NullableBool.True);
format.getBullet().getColor().setColor(Color.BLACK);
if (type == BulletType.Numbered) {
format.getBullet().setNumberedBulletStyle(style);
format.getBullet().setNumberedBulletStartWith(start);
} else if (type == BulletType.Symbol) {
format.getBullet().setChar('\u2022');
} else if (type == BulletType.Picture) {
format.getBullet().getPicture().setImage(bulletImage);
}
textFrame.getParagraphs().add(paragraph);
}
}
ListBuilder list = new ListBuilder();
list.addParagraph("First item", (short) 0, BulletType.Numbered, (short) 5, NumberedBulletStyle.BulletArabicPeriod);
list.addParagraph("Second item", (short) 0, BulletType.Numbered, (short) 5, NumberedBulletStyle.BulletArabicPeriod);
list.addParagraph("Nested item", (short) 1, BulletType.Numbered, (short) 3, NumberedBulletStyle.BulletAlphaLCPeriod);
list.addParagraph("Next nested item", (short) 1, BulletType.Numbered, (short) 3, NumberedBulletStyle.BulletAlphaLCPeriod);
list.addParagraph("Deep item", (short) 2, BulletType.Numbered, (short) 4, NumberedBulletStyle.BulletRomanLCPeriod);
list.addParagraph("Back to top level", (short) 0, BulletType.Numbered, (short) 5, NumberedBulletStyle.BulletArabicPeriod);
list.addParagraph("Symbol marker", (short) 0, BulletType.Symbol, (short) 1, NumberedBulletStyle.BulletArabicPeriod);
list.addParagraph("No bullet", (short) 0, BulletType.None, (short) 1, NumberedBulletStyle.BulletArabicPeriod);
list.addParagraph("Picture marker", (short) 0, BulletType.Picture, (short) 1, NumberedBulletStyle.BulletArabicPeriod);
presentation.save("actual_bullet_values.pptx", SaveFormat.Pptx);
} finally {
presentation.dispose();
}
Presentation loadedPresentation = new Presentation("actual_bullet_values.pptx");
try {
IAutoShape loadedShape = (IAutoShape) loadedPresentation.getSlides().get_Item(0).getShapes().get_Item(0);
System.out.println("Text | Depth | Type | Actual value");
for (IParagraph paragraph : loadedShape.getTextFrame().getParagraphs()) {
IBulletFormatEffectiveData bullet = paragraph.getParagraphFormat().getEffective().getBullet();
String marker;
switch (bullet.getType()) {
case BulletType.Numbered:
case BulletType.Symbol:
marker = bullet.getActualBulletValue();
break;
case BulletType.None:
marker = bullet.getActualBulletValue() + " (no bullet)";
break;
case BulletType.Picture:
marker = bullet.getActualBulletValue() + " (image required)";
break;
default:
marker = "unsupported bullet type";
break;
}
String typeName = BulletType.getName(BulletType.class, bullet.getType());
System.out.println(paragraph.getText() + " | " + paragraph.getParagraphFormat().getDepth() + " | " + typeName + " | " + marker);
}
} finally {
loadedPresentation.dispose();
}
Исходные списки показаны ниже.

Отчёт соответствует маркерам, отображаемым в PowerPoint:
Text | Depth | Type | Actual value
First item | 0 | Numbered | 5.
Second item | 0 | Numbered | 6.
Nested item | 1 | Numbered | c.
Next nested item | 1 | Numbered | d.
Deep item | 2 | Numbered | iv.
Back to top level | 0 | Numbered | 7.
Symbol marker | 0 | Symbol | •
No bullet | 0 | None | null (no bullet)
Picture marker | 0 | Picture | null (image required)
Для BulletType.None and BulletType.Picture метод getActualBulletValue возвращает null, а не пустую строку. Обрабатывайте эти типы отдельно: у первого нет маркера, у второго требуется отдельное извлечение изображения маркера. Маркер‑картинка не может быть воссоздана только путем извлечения текстового маркера.
FAQ
Можно ли экспортировать маркированные и нумерованные списки в PDF или изображения?
Да. Aspose.Slides сохраняет форматирование списков, когда целевой формат поддерживает соответствующее расположение текста и функции маркеров.
Можно ли редактировать списки в существующих презентациях?
Да. Загрузите презентацию, получите целевой абзац, просмотрите или измените его настройки IParagraphFormat.getBullet, затем сохраните презентацию.
Могут ли списки содержать нелатинский текст?
Да. Текст элементов списка может включать Unicode‑символы, поэтому вы можете создавать списки в многоязычных презентациях. Убедитесь, что шрифты, используемые в презентации, поддерживают необходимые символы.