Customizes the default set of stamps in the StampPickerDialog.


/*
* Copyright © 2014-2026 PSPDFKit GmbH. All rights reserved.
*
* The PSPDFKit Sample applications are licensed with a modified BSD license.
* Please see License for details. This notice may not be removed from this file.
*/
package com.pspdfkit.catalog.examples.java;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import com.pspdfkit.annotations.Annotation;
import com.pspdfkit.annotations.AnnotationProvider;
import com.pspdfkit.annotations.AnnotationType;
import com.pspdfkit.annotations.appearance.AppearanceStreamGenerator;
import com.pspdfkit.annotations.appearance.AssetAppearanceStreamGenerator;
import com.pspdfkit.annotations.configuration.StampAnnotationConfiguration;
import com.pspdfkit.annotations.stamps.CustomStampAppearanceStreamGenerator;
import com.pspdfkit.annotations.stamps.PredefinedStampType;
import com.pspdfkit.annotations.stamps.StampPickerItem;
import com.pspdfkit.catalog.R;
import com.pspdfkit.catalog.SdkExample;
import com.pspdfkit.catalog.tasks.ExtractAssetTask;
import com.pspdfkit.configuration.activity.PdfActivityConfiguration;
import com.pspdfkit.document.PdfDocument;
import com.pspdfkit.ui.PdfActivity;
import com.pspdfkit.ui.PdfActivityIntentBuilder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Showcases how customize the `StampPickerDialog` with custom set of stamps.
*/
public class CustomStampAnnotationsExample extends SdkExample {
public CustomStampAnnotationsExample(@NonNull final Context context) {
super(
context,
R.string.annotationCustomStampAnnotationExampleTitle,
R.string.annotationCustomStampAnnotationExampleDescription);
}
@Override
public void launchExample(
@NonNull final Context context, @NonNull final PdfActivityConfiguration.Builder configuration) {
// Extract the document from the assets. The launched activity will add annotations to that
// document.
ExtractAssetTask.extract(WELCOME_DOC, getTitle(), context, documentFile -> {
// To start the CustomStampAnnotationsActivity create a launch intent using the
// builder.
final Intent intent = PdfActivityIntentBuilder.fromUri(context, Uri.fromFile(documentFile))
.configuration(configuration.build())
.activityClass(CustomStampAnnotationsActivity.class)
.build();
// Start the CustomStampAnnotationsActivity for the extracted document.
context.startActivity(intent);
});
}
/**
* Shows how to implement custom set of annotations for the `StampPickerDialog`.
*/
public static class CustomStampAnnotationsActivity extends PdfActivity {
@NonNull
private final String CUSTOM_AP_STREAM_SUBJECT = "CustomApStream";
@NonNull
private final CustomStampAppearanceStreamGenerator customStampAppearanceStreamGenerator =
new CustomStampAppearanceStreamGenerator();
/**
* Appearance stream generator instance set via {@link
* Annotation#setAppearanceStreamGenerator(AppearanceStreamGenerator)} is not retained after
* reloading the document. Custom appearance stream generated for stamps created via stamp
* picker item created in {@link #createCustomApStreamStampItem} will be retained in he reloaded
* document (and in other PDF viewers), however its appearance will be regenerated with default
* appearance stream after the annotation is modified. This has to be called on the main thread.
*
* <p>We register an instance of {@link CustomStampAppearanceStreamGenerator} on {@link
* AnnotationProvider} to regenerate proper appearance for modified stamps based on their custom
* subject.
*
* @param document Loaded document instance.
*/
@UiThread
@Override
public void onDocumentLoaded(@NonNull PdfDocument document) {
super.onDocumentLoaded(document);
document.getAnnotationProvider().addAppearanceStreamGenerator(customStampAppearanceStreamGenerator);
if (getPdfFragment() != null) {
configureStampAnnotationsDefaults();
}
}
/**
* Shows how to configure annotation defaults and control which properties are going to be
* displayed in annotation inspector.
*/
private void configureStampAnnotationsDefaults() {
// Create list of stamps that are going to be added to the picker.
final List<StampPickerItem> items = new ArrayList<>();
// Adding built in stamps.
items.add(StampPickerItem.fromPredefinedType(this, PredefinedStampType.ACCEPTED)
.build());
items.add(StampPickerItem.fromPredefinedType(this, PredefinedStampType.REJECTED)
.build());
// Adding custom subject stamps.
items.add(StampPickerItem.fromTitle(this, "Great!").build());
items.add(StampPickerItem.fromTitle(this, "Stamp!").build());
// Adding custom subject stamps with date-time subtext.
items.add(StampPickerItem.fromTitle(this, "Like")
.withDateTimeSubtitle(true, true)
.build());
// Adding custom bitmap based stamps.
StampPickerItem bitmapStampItem = createBitmapStampItem();
if (bitmapStampItem != null) {
items.add(bitmapStampItem);
}
// Adding custom AP stream based stamps.
items.add(createCustomApStreamStampItem());
// Defaults can be configured through PdfFragment for each annotation type.
getPdfFragment()
.getAnnotationConfiguration()
.put(
AnnotationType.STAMP,
StampAnnotationConfiguration.builder(this)
// Here you return list of stamp picker items that are going to be
// available in the stamp picker.
.setAvailableStampPickerItems(items)
.build());
}
/** This example shows how to create stamp picker item from bitmap image. */
@Nullable
private StampPickerItem createBitmapStampItem() {
try {
final Bitmap bitmap = BitmapFactory.decodeStream(getAssets().open("media/images/exampleimage.jpg"));
return StampPickerItem.fromBitmap(bitmap)
.withSize(StampPickerItem.DEFAULT_STAMP_ANNOTATION_PDF_WIDTH)
.build();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
/**
* This example shows how to create stamp picker item from PDF file containing transparent
* vector image.
*/
@NonNull
private StampPickerItem createCustomApStreamStampItem() {
// We supply our logo image from assets.
AssetAppearanceStreamGenerator appearanceStreamGenerator =
new AssetAppearanceStreamGenerator("images/Nutrient_Logo.pdf");
// Create picker item from custom subject with appearance stream generator set.
StampPickerItem stampPickerItem = StampPickerItem.fromTitle(this, CUSTOM_AP_STREAM_SUBJECT)
.withSize(StampPickerItem.DEFAULT_STAMP_ANNOTATION_PDF_WIDTH)
.withAppearanceStreamGenerator(appearanceStreamGenerator)
.build();
// We want to generate the same AP stream for all stamps with CUSTOM_AP_STREAM_SUBJECT even
// after the document is reloaded.
// customStampAppearanceStreamGenerator will be registered as appearance
// stream generator for document annotations once the document is loaded.
// see onDocumentLoaded below.
customStampAppearanceStreamGenerator.addAppearanceStreamGenerator(
CUSTOM_AP_STREAM_SUBJECT, appearanceStreamGenerator);
return stampPickerItem;
}
}
}

This code sample is an example that illustrates how to use our SDK. Please adapt it to your specific use case.