---
title: "Custom Note Hinter"
canonical_url: "https://www.nutrient.io/guides/android/samples/custom-note-hinter-kotlin/"
md_url: "https://www.nutrient.io/guides/android/samples/custom-note-hinter-kotlin.md"
last_updated: "2025-07-02T00:00:00.000Z"
description: "Display custom note indicator drawables on ink annotations using PdfDrawableProvider."
---

# Custom Note Hinter

Display custom note indicator drawables on ink annotations using PdfDrawableProvider.

[Get Started](https://www.nutrient.io/sdk/android/getting-started.md)

[All Samples](https://www.nutrient.io/guides/android/samples.md)

[Download](https://www.nutrient.io/guides/android/downloads.md)

[Launch Demo](https://www.nutrient.io/demo/)

---

```kotlin

/*
 *   Copyright © 2020-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.kotlin

import android.content.Context
import android.graphics.Canvas
import android.graphics.ColorFilter
import android.graphics.Matrix
import android.graphics.PixelFormat
import android.graphics.PointF
import android.graphics.Rect
import android.graphics.RectF
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Bundle
import android.text.TextUtils
import androidx.annotation.IntRange
import androidx.core.content.ContextCompat
import androidx.core.graphics.drawable.DrawableCompat
import com.pspdfkit.annotations.Annotation
import com.pspdfkit.annotations.AnnotationProvider.OnAnnotationUpdatedListener
import com.pspdfkit.annotations.AnnotationType
import com.pspdfkit.catalog.R
import com.pspdfkit.catalog.SdkExample
import com.pspdfkit.catalog.tasks.ExtractAssetTask
import com.pspdfkit.catalog.utils.Utils
import com.pspdfkit.configuration.activity.PdfActivityConfiguration
import com.pspdfkit.document.PdfDocument
import com.pspdfkit.ui.PdfActivity
import com.pspdfkit.ui.PdfActivityIntentBuilder
import com.pspdfkit.ui.drawable.PdfDrawable
import com.pspdfkit.ui.drawable.PdfDrawableProvider

/**
 * Shows how to create a custom annotation note hinter extending [PdfDrawableProvider].
 */
class CustomAnnotationNoteHinterProviderExample(context: Context) :
    SdkExample(
        context,
        R.string.customAnnotationNoteHinterProviderExampleTitle,
        R.string.customAnnotationNoteHinterProviderExampleDescription,
    ) {
    override fun launchExample(context: Context, configuration: PdfActivityConfiguration.Builder) {
        // Disable default annotation hinter provider.
        configuration.setAnnotationNoteHintingEnabled(false)

        // We use a custom utility class to extract the example document from the assets.
        ExtractAssetTask.extract(WELCOME_DOC, title, context) { documentFile ->
            // To start the CustomAnnotationNoteHinterProviderActivity create a launch intent using the builder.
            val intent =
                PdfActivityIntentBuilder.fromUri(context, Uri.fromFile(documentFile)).configuration(configuration.build()).activityClass(CustomAnnotationNoteHinterProviderActivity::class).build()

            // Start the activity for the extracted document.
            context.startActivity(intent)
        }
    }
}

class CustomAnnotationNoteHinterProviderActivity : PdfActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val customAnnotationNoteHinter = CustomAnnotationNoteHinter(this)

        // Inject our custom hinter to the framework.
        requirePdfFragment().apply {
            // We need to register custom drawable provider so we can provide our custom hint drawables.
            addDrawableProvider(customAnnotationNoteHinter)

            //  We also want to react to annotation updated events in our hinter.
            requirePdfFragment().addOnAnnotationUpdatedListener(customAnnotationNoteHinter)
        }
    }
}

/**
 * A custom annotation note hinter provider that works only for ink annotations.
 */
private class CustomAnnotationNoteHinter(private val pdfActivity: PdfActivity) :
    PdfDrawableProvider(),
    OnAnnotationUpdatedListener {
    private val noteIcon: Drawable =
        ContextCompat.getDrawable(pdfActivity, R.drawable.ic_pin_drop)?: throw IllegalStateException("Can't retrieve note drawable from resources.")

    override suspend fun getDrawablesForPage(
        context: Context,
        document: PdfDocument,
        @IntRange(from = 0) pageIndex: Int,
    ): List<PdfDrawable> = document.annotationProvider.getAnnotations(pageIndex).asSequence().filter { it.type == AnnotationType.INK }.map { NoteInkHinterDrawable(pdfActivity, noteIcon, it) }.toList()

    // We notify change to provided drawables whenever any ink annotation changes (is created, updated or removed).
    override fun onAnnotationCreated(annotation: Annotation) = notifyDrawablesChangedIfSupported(annotation)

    override fun onAnnotationUpdated(annotation: Annotation) = notifyDrawablesChangedIfSupported(annotation)

    override fun onAnnotationRemoved(annotation: Annotation) = notifyDrawablesChangedIfSupported(annotation)

    private fun notifyDrawablesChangedIfSupported(annotation: Annotation) {
        if (annotation.type == AnnotationType.INK) {
            notifyDrawablesChanged()
        }
    }

    // There's no need to update note hinter drawables on Annotation Z-order changes. This method is a no-op.
    override fun onAnnotationZOrderChanged(pageIndex: Int, oldOrder: List<Annotation>, newOrder: List<Annotation>) = Unit
}

private class NoteInkHinterDrawable internal constructor(
    private val activity: PdfActivity,
    private val noteIcon: Drawable,
    private val annotation: Annotation,
) : PdfDrawable() {
    private val viewBoundingBoxRounded: Rect = Rect()
    private val pdfBoundingBox: RectF = RectF()
    private val viewPoint: PointF = PointF()
    private val viewBoundingBox: RectF = RectF()
    private val widthPx: Int
    private val heightPx: Int
    private val halfWidthPx: Int
    private val halfHeightPx: Int

    init {
        annotation.getBoundingBox(pdfBoundingBox)
        widthPx = Utils.dpToPx(activity, 24)
        heightPx = Utils.dpToPx(activity, 24)
        halfWidthPx = widthPx / 2
        halfHeightPx = heightPx / 2
    }

    override fun draw(canvas: Canvas) {
        invalidateSelf()
        if (TextUtils.isEmpty(annotation.contents)) {
            return
        }
        DrawableCompat.setTint(noteIcon, annotation.color)
        noteIcon.bounds = viewBoundingBoxRounded
        noteIcon.draw(canvas)
    }

    override fun setAlpha(@IntRange(from = 0, to = 255) alpha: Int) {
        noteIcon.alpha = ALPHA
    }

    override fun setColorFilter(colorFilter: ColorFilter?) {
        noteIcon.colorFilter = colorFilter
    }

    @Deprecated("Deprecated in Java")
    override fun getOpacity(): Int = PixelFormat.TRANSLUCENT

    override fun updatePdfToViewTransformation(matrix: Matrix) {
        super.updatePdfToViewTransformation(matrix)

        annotation.getBoundingBox(pdfBoundingBox)
        viewPoint.set(pdfBoundingBox.centerX(), pdfBoundingBox.centerY())

        activity.requirePdfFragment().viewProjection.toViewPoint(viewPoint, annotation.pageIndex)

        viewBoundingBox.set(
            viewPoint.x - halfWidthPx,
            viewPoint.y - halfHeightPx,
            viewPoint.x + halfWidthPx,
            viewPoint.y + halfHeightPx,
        )
        viewBoundingBox.round(viewBoundingBoxRounded)
    }

    companion object {
        private const val ALPHA = 255
    }
}

```

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

---

## Related pages

- [Add LTV to Existing Signature](/guides/android/samples/add-ltv-to-existing-signature-kotlin.md)
- [AES Encrypted File](/guides/android/samples/aes-encrypted-file-java.md)
- [AI Assistant (Multiple Documents, Compose)](/guides/android/samples/ai-assistant-multiple-documents-compose-kotlin.md)
- [AI Assistant (Multiple Documents, ViewPager)](/guides/android/samples/ai-assistant-multiple-documents-viewpager-kotlin.md)
- [AI Assistant (Single Document)](/guides/android/samples/ai-assistant-single-document-kotlin.md)
- [Annotation Configuration](/guides/android/samples/annotation-configuration-kotlin.md)
- [Annotation Creation](/guides/android/samples/annotation-creation-kotlin.md)
- [Annotation Flags](/guides/android/samples/annotation-flags-kotlin.md)
- [Annotation Overlay](/guides/android/samples/annotation-overlay-java.md)
- [Annotation Rendering](/guides/android/samples/annotation-rendering-kotlin.md)
- [Annotation Selection Styling](/guides/android/samples/annotation-selection-styling-kotlin.md)
- [Annotation Sidebar](/guides/android/samples/annotation-sidebar-kotlin.md)
- [Annotations with Transparency](/guides/android/samples/annotations-with-transparency-kotlin.md)
- [Application Policy](/guides/android/samples/application-policy-kotlin.md)
- [Bookmark Highlighting](/guides/android/samples/bookmark-highlighting-kotlin.md)
- [Compose Image Document](/guides/android/samples/compose-image-document-kotlin.md)
- [Compose Navigation](/guides/android/samples/compose-navigation-kotlin.md)
- [Construction Floor Plan](/guides/android/samples/construction-floor-plan-kotlin.md)
- [Custom ActionBar Actions](/guides/android/samples/custom-actionbar-actions-kotlin.md)
- [Custom Activity Form Editing](/guides/android/samples/custom-activity-form-editing-java.md)
- [Custom Activity Toolbars](/guides/android/samples/custom-activity-toolbars-java.md)
- [Custom Annotation Creation Toolbar](/guides/android/samples/custom-annotation-creation-toolbar-java.md)
- [Custom Annotation Inspector](/guides/android/samples/custom-annotation-inspector-java.md)
- [Custom Data Provider](/guides/android/samples/custom-data-provider-kotlin.md)
- [Custom Download Dialog](/guides/android/samples/custom-download-dialog-java.md)
- [Custom Electronic Signature](/guides/android/samples/custom-electronic-signature-java.md)
- [Custom Form Highlight Color](/guides/android/samples/custom-form-highlight-color-java.md)
- [Custom Layout](/guides/android/samples/custom-layout-kotlin.md)
- [Custom Main Toolbar](/guides/android/samples/custom-main-toolbar-kotlin.md)
- [Custom Outline Provider](/guides/android/samples/custom-outline-provider-kotlin.md)
- [Custom Page Templates](/guides/android/samples/custom-page-templates-java.md)
- [Custom Search UI (Compose)](/guides/android/samples/custom-search-ui-compose-kotlin.md)
- [Custom Search UI (Views)](/guides/android/samples/custom-search-ui-views-java.md)
- [Custom Sharing Dialog](/guides/android/samples/custom-sharing-dialog-java.md)
- [Custom Sharing Menu](/guides/android/samples/custom-sharing-menu-java.md)
- [Custom Stamp Annotations](/guides/android/samples/custom-stamp-annotations-java.md)
- [Custom Toolbar Grouping](/guides/android/samples/custom-toolbar-grouping-java.md)
- [Digital Signature (Basic)](/guides/android/samples/digital-signature-basic-kotlin.md)
- [Digital Signature (Manual)](/guides/android/samples/digital-signature-manual-kotlin.md)
- [Digital Signature (Third-Party)](/guides/android/samples/digital-signature-third-party-kotlin.md)
- [Digital Signature (Two-Step)](/guides/android/samples/digital-signature-two-step-kotlin.md)
- [Disabled Annotation Property](/guides/android/samples/disabled-annotation-property-java.md)
- [Document Comparison](/guides/android/samples/document-comparison-kotlin.md)
- [Document Download](/guides/android/samples/document-download-kotlin.md)
- [Document from Canvas](/guides/android/samples/document-from-canvas-kotlin.md)
- [Document Processing](/guides/android/samples/document-processing-kotlin.md)
- [Document Sharing](/guides/android/samples/document-sharing-java.md)
- [Document Switcher](/guides/android/samples/document-switcher-java.md)
- [DocumentView Composable](/guides/android/samples/documentview-composable-kotlin.md)
- [Download Progress](/guides/android/samples/download-progress-kotlin.md)
- [Dynamic Pages on Scroll](/guides/android/samples/dynamic-pages-on-scroll-kotlin.md)
- [E-Learning](/guides/android/samples/e-learning-kotlin.md)
- [Electronic + Digital Signing](/guides/android/samples/electronic-digital-signing-kotlin.md)
- [External Document](/guides/android/samples/external-document-kotlin.md)
- [File Annotation Creation](/guides/android/samples/file-annotation-creation-kotlin.md)
- [Filterable Thumbnail Grid](/guides/android/samples/filterable-thumbnail-grid-kotlin.md)
- [Form Click Intercept (Compose)](/guides/android/samples/form-click-intercept-compose-kotlin.md)
- [Form Creation](/guides/android/samples/form-creation-kotlin.md)
- [Form Filling](/guides/android/samples/form-filling-kotlin.md)
- [Forms with JavaScript](/guides/android/samples/forms-with-javascript-kotlin.md)
- [Fragment Runtime Configuration](/guides/android/samples/fragment-runtime-configuration-kotlin.md)
- [Generate PDF Report](/guides/android/samples/generate-pdf-report-kotlin.md)
- [Hide and Reveal Areas](/guides/android/samples/hide-and-reveal-areas-kotlin.md)
- [HTML-to-PDF Conversion](/guides/android/samples/html-to-pdf-conversion-kotlin.md)
- [Image Document](/guides/android/samples/image-document-kotlin.md)
- [Inline Multimedia](/guides/android/samples/inline-multimedia-kotlin.md)
- [Inline Search](/guides/android/samples/inline-search-java.md)
- [Instant Document JSON](/guides/android/samples/instant-document-json-kotlin.md)
- [Instant JSON Attachment](/guides/android/samples/instant-json-attachment-kotlin.md)
- [JavaScript Actions](/guides/android/samples/javascript-actions-kotlin.md)
- [JavaScript Calculator](/guides/android/samples/javascript-calculator-kotlin.md)
- [JavaScript Form Filling](/guides/android/samples/javascript-form-filling-kotlin.md)
- [Kiosk Grid](/guides/android/samples/kiosk-grid-kotlin.md)
- [LTV Signature](/guides/android/samples/ltv-signature-kotlin.md)
- [Measurement Tools](/guides/android/samples/measurement-tools-kotlin.md)
- [Merge Documents](/guides/android/samples/merge-documents-kotlin.md)
- [Multimedia Annotations](/guides/android/samples/multimedia-annotations-kotlin.md)
- [Multiple Documents (Compose Pager)](/guides/android/samples/multiple-documents-compose-pager-kotlin.md)
- [OCR](/guides/android/samples/ocr-kotlin.md)
- [Overlay Views](/guides/android/samples/overlay-views-kotlin.md)
- [Overlay Visibility](/guides/android/samples/overlay-visibility-kotlin.md)
- [Password Protected PDF](/guides/android/samples/password-protected-pdf-kotlin.md)
- [PDF from Image](/guides/android/samples/pdf-from-image-kotlin.md)
- [PdfFragment](/guides/android/samples/pdffragment-kotlin.md)
- [PdfUiFragment](/guides/android/samples/pdfuifragment-kotlin.md)
- [Playground](/guides/android/samples/playground-kotlin.md)
- [Popup Toolbar Customization](/guides/android/samples/popup-toolbar-customization-kotlin.md)
- [Programmatic Zoom](/guides/android/samples/programmatic-zoom-kotlin.md)
- [Reader View](/guides/android/samples/reader-view-kotlin.md)
- [Remote URL](/guides/android/samples/remote-url-kotlin.md)
- [Runtime Configuration](/guides/android/samples/runtime-configuration-kotlin.md)
- [Scientific Paper](/guides/android/samples/scientific-paper-kotlin.md)
- [Screen Reader](/guides/android/samples/screen-reader-java.md)
- [Search Indexing](/guides/android/samples/search-indexing-kotlin.md)
- [Selection Customization](/guides/android/samples/selection-customization-java.md)
- [Signature Parcelize](/guides/android/samples/signature-parcelize-kotlin.md)
- [Signature Storage Database](/guides/android/samples/signature-storage-database-kotlin.md)
- [Sound Extraction](/guides/android/samples/sound-extraction-kotlin.md)
- [Split View](/guides/android/samples/split-view-java.md)
- [Tabbed Documents](/guides/android/samples/tabbed-documents-kotlin.md)
- [Tabbed Documents (Persistent)](/guides/android/samples/tabbed-documents-persistent-kotlin.md)
- [Text Field Suggestions](/guides/android/samples/text-field-suggestions-kotlin.md)
- [Thumbnail Bar Modes](/guides/android/samples/thumbnail-bar-modes-kotlin.md)
- [Try Instant](/guides/android/samples/try-instant-kotlin.md)
- [UI View Modes](/guides/android/samples/ui-view-modes-kotlin.md)
- [Vertical Scrollbar](/guides/android/samples/vertical-scrollbar-java.md)
- [Watermarks](/guides/android/samples/watermarks-kotlin.md)
- [XFDF Import/Export](/guides/android/samples/xfdf-import-export-kotlin.md)

