Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import 'package:flutter_pdfview/flutter_pdfview.dart';
| nightMode | ✅ | ❌ | `false` |
| password | ✅ | ✅ | `null` |
| autoSpacing | ✅ | ✅ | `true` |
| spacing | ✅ | ✅ | `0` |
| pageFling | ✅ | ✅ | `true` |
| pageSnap | ✅ | ❌ | `true` |
| preventLinkNavigation | ✅ | ✅ | `false` |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ public class FlutterPDFView implements PlatformView, MethodCallHandler {
.password(getString(params, "password"))
.nightMode(getBoolean(params, "nightMode"))
.autoSpacing(getBoolean(params, "autoSpacing"))
.spacing(getInt(params, "spacing"))
.pageFling(getBoolean(params, "pageFling"))
.pageSnap(getBoolean(params, "pageSnap"))
.pageFitPolicy(getFitPolicy(params))
Expand Down
1 change: 1 addition & 0 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ class _PDFScreenState extends State<PDFScreen> with WidgetsBindingObserver {
: true, // Vertical scrolling is safer on iPad
autoSpacing:
widget.isIPadSafe ? true : false, // Let PDFKit handle spacing
spacing: widget.isIPadSafe ? 0 : 10,
pageFling: widget.isIPadSafe
? false
: true, // Disable page fling to avoid conflicts
Expand Down
4 changes: 2 additions & 2 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ dependencies:

# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^1.0.2
path_provider: ^2.0.1
cupertino_icons: ^1.0.8
path_provider: ^2.1.5
flutter_pdfview:
path: ../

Expand Down
6 changes: 6 additions & 0 deletions ios/flutter_pdfview/Sources/flutter_pdfview/FlutterPDFView.m
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ @implementation FLTPDFView {
PDFDestination* _currentDestination;
BOOL _preventLinkNavigation;
BOOL _autoSpacing;
NSInteger _spacing;
PDFPage* _defaultPage;
BOOL _defaultPageSet;
BOOL _isIPad;
Expand All @@ -120,6 +121,7 @@ - (instancetype)initWithFrame:(CGRect)frame
_pdfView.delegate = self;

_autoSpacing = [args[@"autoSpacing"] boolValue];
_spacing = [args[@"spacing"] integerValue];
BOOL pageFling = [args[@"pageFling"] boolValue];
BOOL enableSwipe = [args[@"enableSwipe"] boolValue];
_preventLinkNavigation = [args[@"preventLinkNavigation"] boolValue];
Expand Down Expand Up @@ -154,6 +156,10 @@ - (instancetype)initWithFrame:(CGRect)frame

_pdfView.autoScales = _autoSpacing;

if (@available(iOS 11.0, *)) {
_pdfView.pageBreakMargins = UIEdgeInsetsMake(_spacing, 0, _spacing, 0);
Comment on lines +159 to +160
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🌐 Web query:

In Apple's PDFKit, how does PDFView.pageBreakMargins affect inter-page spacing when displayDirection is horizontal? Do left/right insets control the visible gap in horizontal paging modes?

💡 Result:

PDFView.pageBreakMargins is only used for the page-break “spacing” layout when displaysPageBreaks == true: it defines extra inset around each page’s frame (top/left/bottom/right), and PDFKit uses that to create the visible separation between adjacent pages. By default, when page breaks are shown, the margins are non‑zero; if page breaks are off, the margins are effectively zero. Negative values are clamped to 0. [1][2]

So when displayDirection == .horizontal in a scroll/continuous layout, the visible gap between pages horizontally is produced by the trailing margin of the left page (right) plus the leading margin of the next page (left) (top/bottom mainly affect vertical padding around the page, not the left↔right inter-page gap). [1]

In contrast, in “paging” setups that aren’t using PDFKit’s page-break spacing (commonly when you enable usePageViewController(true)), pageBreakMargins typically won’t control the inter-page gap because pages aren’t laid out in the same continuous “page breaks” container. (There’s no public API in PDFKit to set UIPageViewController’s internal inter-page spacing.) [1]

Sources:
[1] ComPDFKit CPDFView docs describing displaysPageBreaks and pageBreakMargins semantics (mirrors Apple PDFKit behavior) (developers.compdf.com)
[2] Monkeybread PDFViewMBS.pageBreakMargins notes on defaults + clamping (monkeybreadsoftware.net)

Citations:


🏁 Script executed:

# Search for displaysPageBreaks and usePageViewController in iOS code
rg -t objc -t swift "displaysPageBreaks|usePageViewController" ios/

Repository: endigo/flutter_pdfview

Length of output: 333


🏁 Script executed:

# Read the full FlutterPDFView.m to understand initialization and context
wc -l ios/flutter_pdfview/Sources/flutter_pdfview/FlutterPDFView.m

Repository: endigo/flutter_pdfview

Length of output: 130


🏁 Script executed:

# Look for where _pdfView is initialized and configured
rg -t objc "PDFView|_pdfView\s*=" ios/flutter_pdfview/Sources/flutter_pdfview/ -A 3

Repository: endigo/flutter_pdfview

Length of output: 7515


🏁 Script executed:

# Read context around usePageViewController calls - find line numbers first
rg -t objc "usePageViewController" ios/flutter_pdfview/Sources/flutter_pdfview/FlutterPDFView.m -n -B 5 -A 5

Repository: endigo/flutter_pdfview

Length of output: 793


🏁 Script executed:

# Search for pageFling variable and displayDirection to understand the full layout logic
rg -t objc "pageFling|displayDirection" ios/flutter_pdfview/Sources/flutter_pdfview/FlutterPDFView.m -n -B 2 -A 2

Repository: endigo/flutter_pdfview

Length of output: 1270


🏁 Script executed:

# Read the full initialization section (roughly lines 80-160) to understand context
sed -n '80,160p' ios/flutter_pdfview/Sources/flutter_pdfview/FlutterPDFView.m

Repository: endigo/flutter_pdfview

Length of output: 2745


🏁 Script executed:

# Check if displaysPageBreaks is ever set to true
rg -t objc "displaysPageBreaks" ios/

Repository: endigo/flutter_pdfview

Length of output: 48


Inter-page spacing will not be visible without enabling page breaks on iOS.

pageBreakMargins only affects spacing when displaysPageBreaks is true. The current code never enables page breaks, so the spacing parameter has no effect regardless of inset direction. Even with the conditional inset fix for horizontal/vertical paging, the feature won't work until _pdfView.displaysPageBreaks = YES is set during initialization. Additionally, when using horizontal paging (displayDirection = kPDFDisplayDirectionHorizontal), the visible inter-page gap is controlled by left/right insets, not top/bottom—so UIEdgeInsetsMake(_spacing, 0, _spacing, 0) produces no horizontal spacing.

Possible fix
        _pdfView.autoScales = _autoSpacing;

+       if (`@available`(iOS 11.0, *)) {
+           _pdfView.displaysPageBreaks = YES;
+       }
+
        if (`@available`(iOS 11.0, *)) {
-           _pdfView.pageBreakMargins = UIEdgeInsetsMake(_spacing, 0, _spacing, 0);
+           _pdfView.pageBreakMargins = swipeHorizontal
+               ? UIEdgeInsetsMake(0, _spacing, 0, _spacing)
+               : UIEdgeInsetsMake(_spacing, 0, _spacing, 0);
        }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ios/flutter_pdfview/Sources/flutter_pdfview/FlutterPDFView.m` around lines
159 - 160, The inter-page spacing isn't visible because pageBreakMargins on
_pdfView only works when _pdfView.displaysPageBreaks is enabled and horizontal
spacing requires left/right insets; update the initialization for _pdfView to
set _pdfView.displaysPageBreaks = YES and compute pageBreakMargins based on
displayDirection (use left/right insets of _spacing when displayDirection ==
kPDFDisplayDirectionHorizontal, otherwise use top/bottom insets) so
pageBreakMargins is effective for both horizontal and vertical paging.

}

// On iPad, avoid conflicting display modes with page view controller
if (_isIPad && pageFling && enableSwipe) {
// For iPad with both pageFling and enableSwipe, prefer page-based navigation
Expand Down
8 changes: 8 additions & 0 deletions lib/flutter_pdfview.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class PDFView extends StatefulWidget {
this.password,
this.nightMode = false,
this.autoSpacing = true,
this.spacing = 0,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Reject negative spacing at the API boundary.

spacing is public now, but nothing prevents callers from passing a negative value. Add an assert or clamp here before that value reaches the native renderers.

Small guard
-  })  : assert(filePath != null || pdfData != null),
+  })  : assert(filePath != null || pdfData != null),
+        assert(spacing >= 0),
         super(key: key);

Also applies to: 103-104

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/flutter_pdfview.dart` at line 35, Reject negative spacing at the API
boundary by validating the public spacing value before it reaches native
renderers: in the constructor where spacing is assigned (the spacing parameter /
field) add an assert or clamp (e.g., spacing = spacing < 0 ? 0 : spacing) and
likewise guard any other public setter or alternate constructor usage referenced
near the second occurrence (the code around the other spacing assignment at
lines 103-104) to ensure spacing is non-negative; update any places that forward
spacing to native calls (renderers) to use the validated/clamped value and
include an assert to catch negative inputs in debug builds.

this.pageFling = true,
this.pageSnap = true,
this.enableAntialiasing = true,
Expand Down Expand Up @@ -99,6 +100,9 @@ class PDFView extends StatefulWidget {
/// Indicates whether or not the PDF viewer automatically adds spacing between pages. If set to true, spacing is added.
final bool autoSpacing;

/// Indicates the amount of spacing between pages in the PDF document.
final int spacing;

/// Indicates whether or not the user can "fling" pages in the PDF document. If set to true, page flinging is enabled.
final bool pageFling;

Expand Down Expand Up @@ -247,6 +251,7 @@ class _PDFViewSettings {
this.password,
this.nightMode,
this.autoSpacing,
this.spacing,
this.pageFling,
Comment on lines +254 to 255
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

spacing is create-only right now.

These additions carry spacing into the initial creation params, but updatesMap() still never emits spacing changes, and the native updateSettings paths in this PR don't handle it either. Rebuilding PDFView(spacing: ...) with a new value will silently do nothing after the platform view exists.

Also applies to: 274-275, 313-313

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@lib/flutter_pdfview.dart` around lines 254 - 255, The PDFView spacing prop is
currently create-only: update the Dart side to include spacing in updatesMap()
so changes to the PDFView(spacing: ...) prop are emitted after creation, and
extend the native updateSettings handling code paths (the platform view
update/updateSettings handlers) to accept and apply spacing updates so
rebuilding the widget actually updates the native view; reference the spacing
constructor param, the updatesMap() method, and the native updateSettings
handlers when making the changes.

this.pageSnap,
this.enableAntialiasing,
Expand All @@ -266,6 +271,7 @@ class _PDFViewSettings {
password: widget.password,
nightMode: widget.nightMode,
autoSpacing: widget.autoSpacing,
spacing: widget.spacing,
pageFling: widget.pageFling,
pageSnap: widget.pageSnap,
enableAntialiasing: widget.enableAntialiasing,
Expand All @@ -284,6 +290,7 @@ class _PDFViewSettings {
final String? password;
final bool? nightMode;
final bool? autoSpacing;
final int? spacing;
final bool? pageFling;
final bool? pageSnap;
final bool? enableAntialiasing;
Expand All @@ -303,6 +310,7 @@ class _PDFViewSettings {
'password': password,
'nightMode': nightMode,
'autoSpacing': autoSpacing,
'spacing': spacing,
'pageFling': pageFling,
'pageSnap': pageSnap,
'enableAntialiasing': enableAntialiasing,
Expand Down
2 changes: 2 additions & 0 deletions test/flutter_pdfview_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,14 @@ void main() {
swipeHorizontal: true,
pageFling: false,
pageSnap: false,
spacing: 15,
);

expect(customPdfView.enableSwipe, false);
expect(customPdfView.swipeHorizontal, true);
expect(customPdfView.pageFling, false);
expect(customPdfView.pageSnap, false);
expect(customPdfView.spacing, 15);
});
});

Expand Down