This document refers to the PTDocumentController For the legacy PTDocumentViewController
class, please see this guide .
This article explains how to customize the document viewer classes PTDocumentController
and PTTabbedDocumentViewController
.
Because the document viewer classes are part of the open source Tools UI framework, it is possible to achieve virtually any required modification. That said, it is usually faster and more convenient to configure the viewers via APIs, which this guide describes.
Regular Compact
The above image (items 1–5) indicates areas that are controllable via the PTDocumentController
's API. Information on customizing these is available directly below .
The above image (items 7–12) indicates a number of default buttons that create and present new controls. Information on where to look to customize these presented controls can be found in the component controls table .
The image on the left (items 1–6) indicates areas that are controllable via the PTDocumentController
's API. Information on customizing these is available directly below .
The image on the right (items 7–12) indicates a number of default buttons that create and present new controls. Information on where to look to customize these presented controls can be found in the component controls table .
On iPad and other regular horizontal size class devices, a number of default UI controls are accessible from the navigation bar, whereas on iPhones and compact size classes some of those controls appear in the toolbar at the bottom of the view.
The toolbar switcher can be hidden:
Swift Obj-C
1 documentController.toolGroupIndicatorView.isHidden = true
1 documentController.toolGroupIndicatorView.hidden = YES ;
Toolbars can be removed by removing them from the toolGroupManager's groups array. The following code removes the "Draw" and "Pens" toolbars:
Swift Obj-C
1 var mutableGroups = documentController.toolGroupManager.groups
2
3 let groupsToRemove = [documentController.toolGroupManager.drawItemGroup, documentController.toolGroupManager.pensItemGroup]
4
5 mutableGroups. removeAll ( where : {groupsToRemove. contains ( $0 )})
6
7 documentController.toolGroupManager.groups = mutableGroups
1 NSMutableArray < PTToolGroup *>* mutableGroups = [documentController.toolGroupManager.groups mutableCopy ];
2
3 [mutableGroups removeObjectsInArray :@[documentController.toolGroupManager.drawItemGroup, documentController.toolGroupManager.pensItemGroup]];
4
5 documentController.toolGroupManager.groups = [mutableGroups copy ];
The buttons which are contained in the leftBarButtonItems
and rightBarButtonItems
arrays, are completely customizable. It is possible to
You can modify the navigation bar items. Here is an example of adding a new button (for the current size class):
Swift Obj-C
1 let myItem = UIBarButtonItem ( image : UIImage ( systemName : " square.and.pencil " ), style : .plain, target : nil , action : nil )
2
3 documentController.navigationItem.rightBarButtonItems. append (myItem)
1 UIBarButtonItem * myItem = [[UIBarButtonItem alloc ] initWithImage :[UIImage systemImageNamed : @" square.and.pencil " ] style :UIBarButtonItemStylePlain target : nil action : nil ];
2
3 documentController.navigationItem.rightBarButtonItems = [documentController.navigationItem.rightBarButtonItems arrayByAddingObject :myItem];
Tools can also be added:
Swift Obj-C
1 let freeHand = documentController.toolGroupManager. createItem ( forToolClass :PTFreeHandCreate. self )
2
3 documentController.navigationItem.rightBarButtonItems. append (freeHand)
1 UIBarButtonItem * freeHand = [documentController.toolGroupManager createItemForToolClass :[PTFreeHandCreate class ]];
2
3 documentController.navigationItem.rightBarButtonItems = [documentController.navigationItem.rightBarButtonItems arrayByAddingObject :freeHand];
Note that in the example above, de-selecting the tool button item needs to be implemented by the app, by listening to the Tool Did Change notification.
To remove any of the default buttons see the instructions here: Hide default buttons
The default buttons are all accessible via properties, making it easy to rearrange or move them. The following code swaps the position of the search button and navigation lists button:
Swift Obj-C
1 var rightItems = documentViewController.navigationItem.rightBarButtonItems
2 rightItems ? . removeAll ( where : { element in element == documentViewController.searchButtonItem })
3 rightItems ? . append (documentViewController.navigationListsButtonItem)
4
5 var bottomRightItems:[UIBarButtonItem] ? = documentViewController.thumbnailSliderController.trailingToolbarItems
6 bottomRightItems ? . removeAll ( where : { element in element as NSObject == documentViewController.navigationListsButtonItem })
7 bottomRightItems ? . append (documentViewController.searchButtonItem)
8
9 documentViewController.navigationItem.rightBarButtonItems = rightItems
10 documentViewController.thumbnailSliderController.trailingToolbarItems = bottomRightItems
1 NSMutableArray * rightItems = [documentViewController.navigationItem.rightBarButtonItems mutableCopy ];
2 [rightItems removeObject :documentViewController.searchButtonItem];
3 [rightItems addObject :documentViewController.navigationListsButtonItem];
4
5 NSMutableArray * bottomRightItems = [documentViewController.thumbnailSliderController.trailingToolbarItems mutableCopy ];
6 [bottomRightItems removeObject :documentViewController.navigationListsButtonItem];
7 [bottomRightItems addObject :documentViewController.searchButtonItem];
8
9 documentViewController.navigationItem.rightBarButtonItems = [rightItems copy ];
10 documentViewController.thumbnailSliderController.trailingToolbarItems = [bottomRightItems copy ];
The icons of existing buttons may be changed by creating new UIBarButtonItems
that have the same target and action as an existing item, and replacing the existing item with the new item:
Swift Obj-C
1 // new search UIBarButtonItem
2 let newSearchItem = UIBarButtonItem ( barButtonSystemItem : .search, target : documentController.searchButtonItem.target, action : documentController.searchButtonItem.action)
3
4 // replace old search UIBarButtonItem with new search UIBarButtonItem
5 index = (rightItems as NSArray ? ) ? . index ( of : documentController.searchButtonItem)
6 rightItems ? . removeAll ( where : { element in element == documentController.searchButtonItem })
7 rightItems ? . insert (newSearchItem, at : index ?? 0 )
8
9 // update the icons
10 documentController.navigationItem.rightBarButtonItems = rightItems
1 // new search UIBarButtonItem
2 UIBarButtonItem * newSearchItem = [[UIBarButtonItem alloc ] initWithBarButtonSystemItem :UIBarButtonSystemItemSearch target :documentController.searchButtonItem.target action :documentController.searchButtonItem.action];
3
4 // replace old search UIBarButtonItem with new search UIBarButtonItem
5 index = [rightItems indexOfObject :documentController.searchButtonItem];
6 [rightItems removeObject :documentController.searchButtonItem];
7 [rightItems insertObject :newSearchItem atIndex :index];
8
9 // update the icons
10 documentController.navigationItem.rightBarButtonItems = [rightItems copy ];
The currently-visible annotation toolbar is selected with the toolbar switcher .
The toolbar can be programmatically hidden by setting the mode to view group, which is a special group and the only group where the toolbar is hidden:
Swift Obj-C
1 documentController.toolGroupManager.selectedGroup = documentController.toolGroupManager.viewItemGroup
1 documentController.toolGroupManager.selectedGroup = documentController.toolGroupManager.viewItemGroup;
The toolbar can be shown again by changing the group to any group other than view:
Swift Obj-C
1 documentController.toolGroupManager.selectedGroup = documentController.toolGroupManager.drawItemGroup
1 documentController.toolGroupManager.selectedGroup = documentController.toolGroupManager.drawItemGroup;
The example below shows how to remove the text highlight and text underline button from a toolbar.
Disabling a tool type entirely
If you want to disable a tool entirely, from all toolbars and the long press menu, please use the annotations permissions system.
Swift Obj-C
1 let annotateGroup = documentController.toolGroupManager.annotateItemGroup
2
3 // tool buttons that exist currently
4 let defaultAnnotateGroupTools = annotateGroup.barButtonItems
5
6 // new set of tools to replace current ones
7 var newAnnotateGroupTools = [UIBarButtonItem]()
8
9 // add all currently existing tools except for the ones we don't want
10 for defaultToolItem in defaultAnnotateGroupTools
11 {
12 if defaultToolItem. isKind ( of : PTToolBarButtonItem. self ) {
13 let toolBarButton = defaultToolItem as! PTToolBarButtonItem
14 if toolBarButton.toolClass == PTTextHighlightCreate. self ||
15 toolBarButton.toolClass == PTTextUnderlineCreate. self
16 {
17 // do not add this tool
18 continue
19 }
20 else
21 {
22 newAnnotateGroupTools. append (toolBarButton)
23 }
24 }
25 else
26 {
27 newAnnotateGroupTools. append (defaultToolItem)
28 }
29 }
30
31 // assign tools to new array
32 documentController.toolGroupManager.annotateItemGroup.barButtonItems = newAnnotateGroupTools
1 PTToolItemGroup * annotateGroup = documentController.toolGroupManager.annotateItemGroup;
2
3 // tool buttons that exist currently
4 NSArray < UIBarButtonItem *>* defaultAnnotateGroupTools = annotateGroup.barButtonItems;
5
6 // new set of tools to replace current ones
7 NSMutableArray < UIBarButtonItem *>* newAnnotateGroupTools = [[ NSMutableArray alloc ] init ];
8
9 // add all currently existing tools except for the ones we don't want
10 for (UIBarButtonItem * defaultToolItem in defaultAnnotateGroupTools)
11 {
12 if ( [defaultToolItem isKindOfClass :[PTToolBarButtonItem class ]] )
13 {
14 PTToolBarButtonItem * toolBarButton = (PTToolBarButtonItem * )defaultToolItem;
15
16 if ( toolBarButton.toolClass == [PTTextHighlightCreate class ] ||
17 toolBarButton.toolClass == [PTTextUnderlineCreate class ] )
18 {
19 // do not add this tool
20 continue ;
21 }
22 else
23 {
24 [newAnnotateGroupTools addObject :defaultToolItem];
25 }
26 }
27 else
28 {
29 [newAnnotateGroupTools addObject :defaultToolItem];
30 }
31 }
32
33 // assign tools to new array
34 documentController.toolGroupManager.annotateItemGroup.barButtonItems = [newAnnotateGroupTools copy ];
Swift Obj-C
1 // create a mutable array of the current items in the annotation toolbar group
2 var availableTools:[UIBarButtonItem] = documentController.toolGroupManager.annotateItemGroup.barButtonItems
3
4 // create a new toolbar item for freehand annotations
5 let freeHandItem = documentController.toolGroupManager. createItem ( forToolClass : PTFreeHandCreate. self )
6
7 // add the freehand annotation item to the front of the list
8 availableTools. insert (freeHandItem, at : 0 )
9
10 // assign the array back to the annotation toolbar group.
11 documentController.toolGroupManager.annotateItemGroup.barButtonItems = availableTools
1 // create a mutable array of the current items in the annotation toolbar group
2 NSMutableArray < UIBarButtonItem *>* availableTools = [documentController.toolGroupManager.annotateItemGroup.barButtonItems mutableCopy ];
3
4 // create a new toolbar item for freehand annotations
5 UIBarButtonItem * freeHandItem = [documentController.toolGroupManager createItemForToolClass :[PTFreeHandCreate class ]];
6
7 // add the freehand annotation item to the front of the list
8 [availableTools insertObject :freeHandItem atIndex : 0 ];
9
10 // assign the array back to the annotation toolbar group.
11 documentController.toolGroupManager.annotateItemGroup.barButtonItems = [availableTools copy ];
Your app may need a button that does not invoke one of the built in annotation tools. The following code will add a button that calls a selector.
Swift Obj-C
1 let selectableItem = PTSelectableBarButtonItem ( image : UIImage ( systemName : " square.and.pencil " ), style : .plain, target : self , action : #selector ( customToolAction (_:)))
2 selectableItem.title = " Custom Tool "
3
4 documentController.toolGroupManager.annotateItemGroup.barButtonItems. append (selectableItem)
1 PTSelectableBarButtonItem * selectableItem = [[PTSelectableBarButtonItem alloc ] initWithImage :image style :UIBarButtonItemStylePlain target : self action : @ selector ( customToolAction: )];
2 selectableItem.title = @" Custom Tool " ;
3
4 documentController.toolGroupManager.annotateItemGroup.barButtonItems = [documentController.toolGroupManager.annotateItemGroup.barButtonItems arrayByAddingObject :selectableItem];
If you want to toggle the items selection, flip its selected property:
Swift Obj-C
1 @objc func customToolAction ( _ button :PTSelectableBarButtonItem)
2 {
3 button.isSelected = ! button.isSelected
4 }
1 - ( void )customToolAction:(PTSelectableBarButtonItem * )button
2 {
3 button.selected = ! button.selected;
4 }
The page indicator can be enabled/disabled via the pageIndicatorEnabled
property.
The PTPDFViewCtrl
is a UIView
that displays the PDF. It is customizable via is properties/methods and delegate methods.
For an overview see the PTPDFViewCtrl Guide , or the detailed API documentation .
Note that all PDF "interaction" (annotations, form filling, text selection, link following, etc.) is supplementary to the PDFViewCtrl, and is implemented in the open source tools.framework
.
These are the buttons that appear at the bottom of the screen on iPhones and in Compact horizontal size classes. Buttons can be added, removed, or rearranged with convenient APIs.
Swift Obj-C
1 // new button
2 let myItem = UIBarButtonItem ( image : UIImage ( systemName : " square.and.pencil " ), style : .plain, target : nil , action : nil )
3
4 // spacer to keep evenly spaced buttons
5 let spacer = UIBarButtonItem ( barButtonSystemItem : .flexibleSpace, target : nil , action : nil )
6
7 // new array
8 var toolbarItems = documentController.toolbarItems
9
10 // add the new items
11 toolbarItems. append ( contentsOf : [spacer, myItem])
12
13 // set the toolbarItems to the new items
14 documentController.toolbarItems = toolbarItems
1 // new button
2 UIBarButtonItem * myItem = [[UIBarButtonItem alloc ] initWithImage :[UIImage systemImageNamed : @" square.and.pencil " ] style :UIBarButtonItemStylePlain target : nil action : nil ];
3
4 // spacer to keep evenly spaced buttons
5 UIBarButtonItem * spacer = [[UIBarButtonItem alloc ] initWithBarButtonSystemItem :UIBarButtonSystemItemFlexibleSpace target : nil action : nil ];
6
7 // new array
8 NSMutableArray * toolbarItems = [documentController.toolbarItems mutableCopy ];
9
10 // add the new items
11 [toolbarItems addObjectsFromArray :@[spacer, myItem]];
12
13 // set the toolbarItems to the new items
14 documentController.toolbarItems = [toolbarItems copy ];
To remove any of the default buttons see the instructions here: Hide default buttons
To customize the controls that are presented by the PTDocumentController
's default buttons, please see the corresponding guide or API:
Default buttons can be removed ("hidden") using built-in properties.
For example to hide the search and more items buttons:
Swift Obj-C
1 documentController.searchButtonHidden = true
2 documentController.moreItemsButtonHidden = true
1 documentController.searchButtonHidden = YES ;
2 documentController.moreItemsButtonHidden = YES ;
The tabbed document view controller displays a collection of document controllers in tabs.
Tabs can be disabled using the tabsEnabled
property, and the maximum number of allowed tabs can be set using maximumTabCount
.
The current document controller can be accessed via selectedViewController
, and others via documentViewController(at:)
To configure a document controller before it is displayed, conform to and implement the PTTabbedDocumentViewControllerDelegate
method tabbedDocumentViewController(_:willAdd:)
. Note that it is permissible to assign the internal PTDocumentViewController
's delegate to an external object.
Swift Obj-C
1 func tabbedDocumentViewController ( _ tabbedDocumentViewController : PTTabbedDocumentViewController, willAdd documentViewController : PTDocumentViewController) {
2 documentViewController.delegate = self
3 // customize documentViewController
4 }
1 - ( void )tabbedDocumentViewController:(PTTabbedDocumentViewController * )tabbedDocumentViewController willAddDocumentViewController:(PTDocumentViewController * )documentViewController
2 {
3 documentViewController.delegate = self ;
4 // customize documentViewController
5 }