Ink annotations in Xamarin Pdf Viewer (SfPdfViewer)

23 Jun 202124 minutes to read

Xamarin PDF Viewer allows you to include ink annotation in the PDF document and provides options to edit or remove the existing ink annotation in the PDF document.

Inclusion of ink annotation

This section describes how to include ink annotation in PDF viewer control Xamarin.Forms.

Enabling ink annotation mode

Set the AnnotationMode property of the PDF viewer object to ink to enable the ink annotation. By setting this, zooming and scrolling will be disabled and touch interactions will be converted into inks on the PDF pages. Refer to the following code.

SfPdfViewer pdfViewer = new SfPdfViewer();
pdfViewer.AnnotationMode = AnnotationMode.Ink;
<syncfusion:SfPdfViewer x:Name="pdfViewer"/>
<Button x:Name="inkAnnotationButton" Command="{Binding AnnotationModeCommand, Source={x:Reference Name=pdfViewer}}" CommandParameter="Ink" />

Use the following code to reset the annotation mode to none.

SfPdfViewer pdfViewer = new SfPdfViewer();
pdfViewer.AnnotationMode = AnnotationMode.None;
<syncfusion:SfPdfViewer x:Name="pdfViewer"/>
<Button x:Name="resetAnnotationButton" Command="{Binding AnnotationModeCommand, Source={x:Reference Name=pdfViewer}}" CommandParameter="None" />

Adding ink annotation using toolbar

Steps involved in adding ink annotation to the PDF document:

  1. Switch to ink annotation mode.
  2. Add inks to the pages of the PDF document, this will be recorded as a session.
  3. You can perform undo and redo operations for every stroke made in the session.
  4. You can also choose the color and thickness of the ink, here color and thickness are restricted to the complete ink and not individual strokes.
  5. After adding ink annotation, you can either accept or discard the changes.

How to accept and include the ink annotation on to the PDF viewer?

The following code can be used to accept and include the drawn ink annotation to the PDF viewer control.

pdfViewer.EndInkSession(true);

How to ignore/discard drawn ink annotation from the PDF viewer before inclusion?

The following code can be used to ignore or discard the drawn ink annotation to the PDF viewer control.

pdfViewer.EndInkSession(false);

Adding ink annotation programmatically

By AddAnnotation method, You can add the ink annotations programmatically. The created ink annotation object passed as a parameter. The InkAnnotation instance acquires the InkPointsCollection, page number and position as the parameters.

The following code sample illustrates the same.

var inkPointsCollection = new List<List<float>>();

inkPointsCollection.Add(new List<float> { 53f, 525f, 53f, 527f, 53f, 528f, 53f, 531f, 53f, 549f, 54f, 570f, 56f, 597f, 57f, 623f, 59f, 652f, 60f, 679f, 62f, 705f, 64f, 726f, 65f, 744f, 66f, 758f, 66f, 768f, 65f, 777f, 65f, 782f, 65f, 784f, 64f, 786f, 64f, 786f, 63f, 786f, 63f, 786f, 63f, 784f, 66f, 774f, 71f, 757f, 79f, 734f, 88f, 708f, 99f, 681f, 112f, 652f, 126f, 627f, 140f, 606f, 150f, 591f, 158f, 582f, 162f, 578f, 164f, 577f, 165f, 576f, 166f, 576f, 165f, 578f, 155f, 592f, 143f, 605f, 121f, 621f, 99f, 631f, 77f, 639f, 54f, 644f, 35f, 645f, 20f, 644f, 10f, 642f, 4f, 642f, 2f, 641f, 1f, 640f, 0f, 639f, 0f, 639f, 2f, 639f, 20f, 645f, 47f, 657f, 75f, 672f, 106f, 688f, 137f, 704f, 168f, 718f, 197f, 732f, 221f, 741f, 240f, 748f, 254f, 753f, 254f, 753f });

System.Drawing.Point position = new System.Drawing.Point(100, 100);
InkAnnotation inkAnnotation = new InkAnnotation(inkPointsCollection, 1, position);
inkAnnotation.Settings.Color = Color.Red;     
      
//Adds the ink annotation to the specified page 
pdfViewer.AddAnnotation(inkAnnotation);

How to identify whether the ink annotation is included?

You can identify whether the drawn ink annotation has been added to the PDF viewer control or not by using the InkAdded event. This event will be raised once the annotation is added.

<syncfusion:SfPdfViewer x:Name="pdfViewer" InkAdded="PdfViewer_InkAdded"/>
private void PdfViewer_InkAdded(object sender, InkAddedEventArgs args)
{
    //Retrieves the bounds of the deselected annotation.
    Rectangle bounds = args.Bounds;

    //Retrieves the page number where the deselected annotation resides.
    int pageNumber = args.PageNumber;

    //Retrieves the color of the deselected annotation.
    Color color = args.Color;

    //Retrieves the thickness of the deselected annotation.
    float thickness = args.Thickness;

    //Retrieves the opacity of the deselected annotation.
    float opacity = args.Opacity;

}

How to perform undo and redo operation during inking session?

You can perform undo and redo operations on the drawn ink annotations during the pre-conformance session.

The following code can be used to perform undo operation on the ink annotations drawn over the PDF viewer control.

pdfViewer.UndoInk();

You can identify the undo operation in this session using the following event.

<syncfusion:SfPdfViewer x:Name="pdfViewer" CanUndoInkModified = "PdfViewer_CanUndoInkModified" />
private void PdfViewer_CanUndoInkModified(object sender, CanUndoInkModifiedEventArgs args)
{
    bool canUndoInk = args.CanUndoInk;
}

The following code can be used to perform redo operation on the ink annotations drawn over the PDF viewer control.

pdfViewer.RedoInk();

You can identify the redo operation in this session using the following event.

<syncfusion:SfPdfViewer x:Name="pdfViewer" CanRedoInkModified = "PdfViewer_CanRedoInkModified" />
private void PdfViewer_CanRedoInkModified(object sender, CanRedoInkModifiedEventArgs args)
{
         bool CanRedoInk = args.CanRedoInk;
}

Deleting ink annotation

The PDF viewer can remove a selected annotation or all the annotations in the PDF document.

Removing a selected annotation.

The following code snippet illustrates removing a selected annotation from the PDF document.

<syncfusion:SfPdfViewer x:Name="pdfViewer" InkSelected="PdfViewer_InkSelected"/>
private void PdfViewer_InkSelected(object sender, InkSelectedEventArgs args)
{
    //Casts the sender object as Ink annotation.
    InkAnnotation selectedInkAnnotation = sender as InkAnnotation;

    //Removes the selected annotation from the PDF viewer.
    pdfViewer.RemoveAnnotation(selectedInkAnnotation);
}

How to identify the removal of ink annotation?

You can identify removal of ink annotation using the InkRemoved event, which is available in the PDF viewer control. This event will be raised when you remove the ink annotation from the PDF viewer control.

<syncfusion:SfPdfViewer x:Name="pdfViewer" InkRemoved="PdfViewer_InkRemoved"/>

The following C# code shows how to acquire bounds, page number, color, thickness, and opacity of the removed ink annotation.

private void PdfViewer_InkRemoved(object sender, InkRemovedEventArgs args)
{

    //Retrieves the bounds of the deselected annotation.
    Rectangle bounds = args.Bounds;

    //Retrieves the page number where the deselected annotation resides.
    int pageNumber = args.PageNumber;

    //Retrieves the color of the deselected annotation.
    Color color = args.Color;

    //Retrieves the thickness of the deselected annotation.
    float thickness = args.Thickness;

    //Retrieves the opacity of the deselected annotation.
    float opacity = args.Opacity;
}

Working with ink annotation settings

You can customize the color, opacity, and thickness of the ink annotation.

Changing the color

You can set the color of the ink annotation by using the AnnotationSettings.Ink.Color property. Refer to the following code sample.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace: PdfViewerGettingStarted "
             xmlns:syncfusion ="clr-namespace:Syncfusion.SfPdfViewer.XForms;assembly=Syncfusion.SfPdfViewer.XForms"
             x:Class=" PdfViewerGettingStarted.MainPage">

    <ContentPage.Resources>
        <ResourceDictionary>
            <syncfusion:AnnotationSettings x:Key="InkAnnotationSettings">
                <syncfusion:AnnotationSettings.Ink>
                    <Color>#FFFF0000</Color>
                </syncfusion:AnnotationSettings.Ink>               
            </syncfusion:AnnotationSettings>
        </ResourceDictionary>
    </ContentPage.Resources>
    
    <ContentPage.Content>

        <syncfusion:SfPdfViewer x:Name="pdfViewer" AnnotationSettings="{StaticResource InkAnnotationSettings}"/>

    </ContentPage.Content>

</ContentPage>
SfPdfViewer pdfViewer = new SfPdfViewer();

pdfViewer.AnnotationMode = AnnotationMode.Ink;

pdfViewer.AnnotationSettings.Ink.Color = Color.Red;

Changing the opacity

You can set the opacity of the ink annotation by using the AnnotationSettings.Ink.Opacity property. Opacity value ranges from 0 to 1. Refer to the following code example.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace: PdfViewerGettingStarted "
             xmlns:syncfusion ="clr-namespace:Syncfusion.SfPdfViewer.XForms;assembly=Syncfusion.SfPdfViewer.XForms"
             x:Class=" PdfViewerGettingStarted.MainPage">

    <ContentPage.Resources>
        <ResourceDictionary>
            <syncfusion:AnnotationSettings x:Key="InkAnnotationSettings">
                <syncfusion:AnnotationSettings.Ink>
                    <Opacity>0.5</Opacity>
                </syncfusion:AnnotationSettings.Ink>               
            </syncfusion:AnnotationSettings>
        </ResourceDictionary>
    </ContentPage.Resources>
    
    <ContentPage.Content>

        <syncfusion:SfPdfViewer x:Name="pdfViewer" AnnotationSettings="{StaticResource InkAnnotationSettings}"/>

    </ContentPage.Content>

</ContentPage>
SfPdfViewer pdfViewer = new SfPdfViewer();

pdfViewer.AnnotationMode = AnnotationMode.Ink;

pdfViewer.AnnotationSettings.Ink.Opacity = 0.5f;

Changing the thickness

You can set the thickness of the ink annotation by using the AnnotationSettings.Ink.Thickness property. Refer to the following code example.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace: PdfViewerGettingStarted "
             xmlns:syncfusion ="clr-namespace:Syncfusion.SfPdfViewer.XForms;assembly=Syncfusion.SfPdfViewer.XForms"
             x:Class=" PdfViewerGettingStarted.MainPage">

    <ContentPage.Resources>
        <ResourceDictionary>
            <syncfusion:AnnotationSettings x:Key="InkAnnotationSettings">
                <syncfusion:AnnotationSettings.Ink>
                    <Thickness>5</Thickness>
                </syncfusion:AnnotationSettings.Ink>               
            </syncfusion:AnnotationSettings>
        </ResourceDictionary>
    </ContentPage.Resources>
    
    <ContentPage.Content>

        <syncfusion:SfPdfViewer x:Name="pdfViewer" AnnotationSettings="{StaticResource InkAnnotationSettings}"/>

    </ContentPage.Content>

</ContentPage>
SfPdfViewer pdfViewer = new SfPdfViewer();

pdfViewer.AnnotationMode = AnnotationMode.Ink;

pdfViewer.AnnotationSettings.Ink.Thickness = 5;

Changing the minimum size

By the AnnotationSettings.Ink.MinimumSize property, You can set the minimum size to which the ink annotations could be resized.

Refer the following code example:

//Sets the minimum size for the ink annotations
pdfViewer.AnnotationSettings.Ink.MinimumSize = new Size(10, 10);

How to select the ink annotation?

You can select the ink annotation by tapping the annotation.

Select the ink annotation programmatically

By SelectAnnotation method, You can select the ink annotation programmatically. The specified ink annotation object passed as a parameter. The following code example explains the same.

//Selects the specified ink annotation
pdfViewer.SelectAnnotation(inkAnnotation);

NOTE

Once SelectAnnotation method is called and as long as the annotation stays selected, the SelectedAnnotation property will return the same instance as the parameter of this method.

How to change the properties of ink annotation after selection?

You can select and change the properties of the ink annotation using the InkSelected event. This event will be raised when you select the ink annotation. This is illustrated in the following code sample.

<syncfusion:SfPdfViewer x:Name="pdfViewer" InkSelected="PdfViewer_InkSelected" />

You can change the properties of the selected annotation using the InkSelectedEventArgs object. The following code shows how to change the properties of the selected annotation in the InkSelectedEventHandler.

private void pdfViewer_InkSelected(object sender, InkSelectedEventArgs args)
{
    //Casts the sender object as Ink annotation.
    InkAnnotation selectedInkAnnotation = sender as InkAnnotation;

    //Sets the color of the selected annotation using ink annotation settings.
    selectedInkAnnotation.Settings.Color = Color.Blue;

    //Sets the opacity of the selected annotation using ink annotation settings.
    selectedInkAnnotation.Settings.Opacity = 0.3f;

    //Sets the thickness of the selected annotation using ink annotation settings.
    selectedInkAnnotation.Settings.Thickness = 3;
}

You can identify whether the ink annotation is tapped or not using theInkTapped event. This event will be triggered if you tap the ink annotation whether to select or deselect the annotation.

<syncfusion:SfPdfViewer x:Name="pdfViewer" InkTapped="PdfViewer_InkTapped"/>
private void PdfViewer_InkTapped(object sender, InkTappedEventArgs args)
{
    //Retrieves the bounds of the deselected annotation.
    Rectangle bounds = args.Bounds;

    //Retrieves the page number where the deselected annotation resides.
    int pageNumber = args.PageNumber;

    //Retrieves the color of the deselected annotation.
    Color color = args.Color;

    //Retrieves the thickness of the deselected annotation.
    float thickness = args.Thickness;

    //Retrieves the opacity of the deselected annotation.
    float opacity = args.Opacity;
}

How to deselect the ink annotation?

You can deselect the ink annotation by tapping on the selected annotation or on the PDF page. Deselection can be identified using the InkDeselected event.

<syncfusion:SfPdfViewer x:Name="pdfViewer" InkDeselected="PdfViewer_InkDeselected"/>

The following code shows how to identify the deselected annotation from the raised event.

private void PdfViewer_InkDeselected(object sender, InkDeselectedEventArgs args)
{ 
       //Retrieves the bounds of the deselected annotation.
   Rectangle bounds = args.Bounds;

   //Retrieves the page number where the deselected annotation resides.
   int page = args.PageNumber;

   //Retrieves the color of the deselected annotation.
   Color color = args.Color;

   //Retrieves the thickness of the deselected annotation.
   float thickness = args.Thickness;

   //Retrieves the opacity of the deselected annotation.
   float opacity = args.Opacity;
 
 }

Deselect the ink annotation programmatically

By DeselectAnnotation method, You can deselect the ink annotation programmatically. The specified ink annotation object passed as a parameter.

The following code Sample illustrates the same.

//Deselects the specified ink annotation
pdfViewer.DeselectAnnotation(inkAnnotation);

NOTE

There is no effect in calling DeselectAnnotation method if the given annotation is not selected. Once this method is called, the SelectedAnnotation property will return null until any other annotation gets selected.

How to move or resize the selected ink annotation?

Select and drag the annotation to move or resize the ink annotation.

How to identify whether the ink annotation is moved or resized?

The event AnnotationMovedOrResized will be raised when you move or resize the selected annotation.

<syncfusion:SfPdfViewer x:Name="pdfViewer" AnnotationMovedOrResized="PdfViewer_AnnotationMovedOrResized"/>
private void PdfViewer_AnnotationMovedOrResized(object sender, AnnotationMovedOrResizedEventArgs args) 
{
     //Retrieves the old bounds of the annotation
     Rectangle oldBounds = args.OldBounds;

     //Retrieves the new bounds of the annotation
     Rectangle newBounds = args.NewBounds;
}

How to enable or disable ink annotation interaction?

The interaction operation can be enabled or disabled for ink annotation alone by setting the IsLocked API to false or true respectively.

For example, the following code disables the interaction operations for all ink annotations in the PDF. But other annotation types can be selected, moved, resized, or removed.

//Disable the ink annotation interaction
pdfViewerControl.AnnotationSettings.Ink.IsLocked = true;

The interaction with ink annotation types will be allowed only if the SfPdfViewer.AnnotationSettings.IsLocked API is set to false. The following code does not allow the interactions with ink annotations, although the IsLocked property of the ink annotation is set to false.

//Disables the ink annotation interaction, though its 'IsLocked' property is set to ‘false’ 
pdfViewerControl.AnnotationSettings.IsLocked = true;
pdfViewerControl.AnnotationSettings.Ink.IsLocked = false;

How to draw the ink annotation using a stylus and scroll or zoom PDF page with the touch

The ink annotation operation can be customized so that the ink strokes can be added only using a stylus by setting the InkAnnotationSettings.TouchMode API to TouchMode.Stylus. When the TouchMode is set to stylus, the PDF can be zoomed and scrolled using a finger. The default value of the TouchMode property is TouchMode.Direct in which all touch interactions will be considered as ink operations. So in the TouchMode.Direct mode, the page cannot be scrolled or zoomed when the ink annotation mode is on.

//TouchMode is set to Stylus
pdfViewerControl.AnnotationSettings.Ink.TouchMode = TouchMode.Stylus;

NOTE

At present, this feature is available only in iOS

How to render Ink strokes using custom ink points?

By default, ink strokes are drawn by recording the points on the screen traversed by the input device (stylus or finger). The quality of the strokes thus drawn may not be satisfactory as it considers only raw points. If needed, the points can be modified using any algorithms to smoothen the strokes.

When the ink session ends after drawing the strokes, the InkAdded event will be raised. The InkAnnotation instance that is drawn on the page is exposed as sender argument of the InkAdded event. We can get the Ink points which we drew on the page from InkAnnotation.InkPointsCollection. The InkPointsCollection is of a type List<List>. Each List in this collection represents each stroke of the Ink annotation we drew. There are as many List instances in the [InkPointsCollection](https://help.syncfusion.com/cr/xamarin/Syncfusion.SfPdfViewer.XForms.InkAnnotation.html#Syncfusion_SfPdfViewer_XForms_InkAnnotation_InkPointsCollection) as the number of strokes in the Ink annotation.

The List in turn, has the series of alternate X and Y coordinates of the ink stroke. i.e. the values at the odd position are X coordinates and at the even position are Y coordinates.

We can modify or add new stroke points in the InkAnnotation.InkPointsCollection. As soon as the InkAdded event handler completes execution, the modified points will be reflected in the ink annotation on the UI.

private void PdfViewerControl_InkAdded(object sender, InkAddedEventArgs args) 
{     
     InkAnnotation inkAnnotation = sender as InkAnnotation;         
 
     List<List<float>> drawnPoints = inkAnnotation.InkPointsCollection; 
 
     //Modify the drawn ink points 
     List<List<float>> modifiedPoints = PerformModification(drawnPoints); 
 
     inkAnnotation.InkPointsCollection = modifiedPoints; 
}

NOTE

The strokes cannot be smoothened when the user is drawing the strokes as the points are still being recorded. They can be smoothened only after the user confirms the end of the ink session.

How to get and set the name of the ink annotations?

The PDF Viewer allows the users to get and set the name of the ink annotations through the Name API.

The following code sample explains modifying the name of the ink annotation in the InkAdded event.

private void PdfViewerControl_InkAdded(object sender, InkAddedEventArgs args)
{
   if(sender is InkAnnotation)
    {
    (sender as InkAnnotation).Name = "Ink1";
    }
}

NOTE

For illustration purposes, we have only provided the sample for modifying the name of the ink annotation in the InkAdded event. But this can be done in all other events as well.

NOTE

You can also explore our Xamarin.Forms PDF Viewer example to knows the functionalities of each feature.