Skip to content

feat:Add spacing parameter to PDF viewer for customizable page spacing#335

Open
ma-mobile wants to merge 1 commit intoendigo:masterfrom
ma-mobile:master
Open

feat:Add spacing parameter to PDF viewer for customizable page spacing#335
ma-mobile wants to merge 1 commit intoendigo:masterfrom
ma-mobile:master

Conversation

@ma-mobile
Copy link

@ma-mobile ma-mobile commented Mar 11, 2026

1 - Add custom spacing option to PDFView
2 - Added spacing parameter to PDFView widget (defaults to 0)
3 - Implemented spacing on Android using com.github.barteksc.pdfviewer
4 - Implemented spacing on iOS using PDFKit pageBreakMargins
5 - Updated README and example app to demonstrate the new feature
6 - Added unit test for spacing parameter

Summary by CodeRabbit

  • New Features

    • Added adjustable page spacing control for PDF viewing, allowing customization of whitespace between pages across platforms.
  • Documentation

    • Added spacing option documentation to the configuration guide.
  • Chores

    • Updated project dependencies.
  • Tests

    • Added test coverage for the new spacing functionality.

@coderabbitai
Copy link

coderabbitai bot commented Mar 11, 2026

Walkthrough

This PR introduces a new spacing parameter across the PDF viewer plugin to control inter-page whitespace. The parameter is threaded through the Dart API, native Android and iOS implementations, with supporting documentation, example usage, and test coverage. No behavioral changes to existing functionality.

Changes

Cohort / File(s) Summary
Documentation & Configuration
README.md, example/pubspec.yaml
Added spacing option to README documentation (default 0); updated transitive dependency versions for cupertino_icons and path_provider.
Dart API Layer
lib/flutter_pdfview.dart, example/lib/main.dart, test/flutter_pdfview_test.dart
Introduced spacing parameter to PDFView widget and _PDFViewSettings; parameter defaults to 0 and is serialized to platform maps. Example sets spacing to 0 (iPad safe) or 10 (normal). Added test case verifying spacing property.
Android Native Implementation
android/src/main/java/io/endigo/plugins/pdfviewflutter/FlutterPDFView.java
Added spacing configuration call to PDFView configurator chain.
iOS Native Implementation
ios/flutter_pdfview/Sources/flutter_pdfview/FlutterPDFView.m
Added _spacing private ivar; reads from initialization parameters and applies via pageBreakMargins (UIEdgeInsetsMake) on iOS 11.0+.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • Fix crash described in #302 #330: Modifies the same FlutterPDFView.java Android file to extend the PDFView configurator chain with additional parameters, establishing a similar pattern for adding configurable options to the native implementation.

Suggested reviewers

  • endigo

Poem

📄✨ A rabbit hops through pages wide,
With spacing now to stretch inside,
Each PDF breathes with newfound grace,
Margins bloom in every space! 🐰

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding a spacing parameter to the PDF viewer for customizable page spacing, which aligns with all modifications across platform implementations and documentation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
test/flutter_pdfview_test.dart (1)

170-177: Assert the platform config, not just the Dart field.

This only proves the constructor stored spacing on the widget. It would still pass if spacing were dropped before the platform view is created. Please add a widget test that pumps PDFView and verifies the mocked platform-view/method-channel payload includes spacing: 15.

Based on learnings: Add tests for new features in 'test/flutter_pdfview_test.dart' including widget creation, configuration, error handling, and mock method channels.

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

In `@test/flutter_pdfview_test.dart` around lines 170 - 177, The test currently
only asserts the Dart widget fields (customPdfView.enableSwipe, swipeHorizontal,
pageFling, pageSnap, spacing) but must assert the platform-view/method-channel
payload; update the test in flutter_pdfview_test.dart to pump a PDFView widget
(PDFView) into the widget tester, ensure the mock platform view/method-channel
is registered/attached, then capture the platform creation payload or the
method-channel call used to create/configure the native view and assert it
includes "spacing": 15; reference the PDFView widget and the mock method channel
or platform view registry used in this test to locate where to intercept and
assert the payload.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@ios/flutter_pdfview/Sources/flutter_pdfview/FlutterPDFView.m`:
- Around line 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.

In `@lib/flutter_pdfview.dart`:
- Around line 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.
- 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.

---

Nitpick comments:
In `@test/flutter_pdfview_test.dart`:
- Around line 170-177: The test currently only asserts the Dart widget fields
(customPdfView.enableSwipe, swipeHorizontal, pageFling, pageSnap, spacing) but
must assert the platform-view/method-channel payload; update the test in
flutter_pdfview_test.dart to pump a PDFView widget (PDFView) into the widget
tester, ensure the mock platform view/method-channel is registered/attached,
then capture the platform creation payload or the method-channel call used to
create/configure the native view and assert it includes "spacing": 15; reference
the PDFView widget and the mock method channel or platform view registry used in
this test to locate where to intercept and assert the payload.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 555cf2d1-bc71-42cb-98e2-cc8a30340038

📥 Commits

Reviewing files that changed from the base of the PR and between bddd0cb and 265c70e.

📒 Files selected for processing (7)
  • README.md
  • android/src/main/java/io/endigo/plugins/pdfviewflutter/FlutterPDFView.java
  • example/lib/main.dart
  • example/pubspec.yaml
  • ios/flutter_pdfview/Sources/flutter_pdfview/FlutterPDFView.m
  • lib/flutter_pdfview.dart
  • test/flutter_pdfview_test.dart

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

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.

this.password,
this.nightMode = false,
this.autoSpacing = true,
this.spacing = 0,
Copy link

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.

Comment on lines +254 to 255
this.spacing,
this.pageFling,
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants