docx_viewer_plus 1.1.3
docx_viewer_plus: ^1.1.3 copied to clipboard
A Flutter package for viewing and editing .docx files. Supports rich text editing, customizable toolbar, and cross-platform save.
docx_viewer_plus #
A powerful Flutter package for viewing, editing, and sharing
.docx (Microsoft Word) files directly inside your app. Built
for Android, iOS, and macOS with zero external dependencies on
native document libraries.
Features #
-
DOCX Viewing — Parse and display .docx files with styles, tables, images, lists, and headings preserved
-
Rich Text Editing — Inline editing via WebView with bold, italic, underline, headings, alignment, lists, colors, links, and more
-
Customizable Toolbar — Show/hide individual buttons, reorder, add custom icons, control position (top/bottom)
-
Save & Share — Convert edited content back to .docx, save locally, or share via system share sheet
-
RTL Language Support — Arabic, Urdu, Hebrew, etc.
-
Localization — Built-in strings for English, Arabic, Urdu, Spanish; easy to add more
-
Isolate-Based Processing — Heavy parsing/packaging runs off the UI thread for smooth performance
Supported Formats #
- ✅ .docx (Microsoft Word Open XML)
- ❌ .doc (Legacy binary Word format not supported)
Note: This package only supports modern DOCX files. Older DOC files must be converted to DOCX before use.
Installation #
dependencies:
docx_viewer_plus: ^1.1.3
Quick Start #
Case 1: View-Only Mode #
import 'package:docx_viewer_plus/docx_viewer_plus.dart';
DocxViewerWidget(
filePath: '/path/to/document.docx',
config: DocxViewerConfig(isReadOnly: true),
)
Case 2: Edit Mode with Save & Share #
final _viewerKey = GlobalKey<DocxViewerWidgetState>();
DocxViewerWidget(
key: _viewerKey,
filePath: '/path/to/document.docx',
config: DocxViewerConfig(
toolbarPosition: ToolbarPosition.bottom,
),
)
// Save button
onPressed: () async {
final path = await _viewerKey.currentState?.save(
outputPath: '/path/to/output.docx',
);
if (path != null) print('Saved: $path');
},
// Share button
onPressed: () async {
final bytes = await _viewerKey.currentState?.getDocxBytes();
if (bytes == null) return;
final dir = await getTemporaryDirectory();
final file = File('${dir.path}/shared.docx');
await file.writeAsBytes(bytes);
await SharePlus.instance.share(
ShareParams(files: [XFile(file.path)]),
);
},
Case 3: Custom Toolbar Options #
DocxViewerWidget(
filePath: '/path/to/document.docx',
config: DocxViewerConfig(
enabledOptions: {
ToolbarOption.bold,
ToolbarOption.italic,
ToolbarOption.underline,
ToolbarOption.heading1,
ToolbarOption.heading2,
ToolbarOption.alignLeft,
ToolbarOption.alignCenter,
ToolbarOption.alignRight,
},
),
)
Case 4: RTL Language Support #
DocxViewerWidget(
filePath: '/path/to/arabic-doc.docx',
config: DocxViewerConfig(
forceTextDirection: TextDirection.rtl,
strings: DocxViewerStrings.arabic,
toolbarPosition: ToolbarPosition.bottom,
),
)
Case 5: Load from Bytes (Asset/Network) #
final service = DocxService();
final bytes = await rootBundle.load('assets/doc.docx');
await service.loadFromBytes(
bytes.buffer.asUint8List(),
fileName: 'document.docx',
);
Case 6: Listen for Content Changes #
DocxViewerWidget(
filePath: '/path/to/document.docx',
onContentChanged: (html) {
print('Content changed, length: ${html.length}');
},
)
Case 7: Custom Save Callback #
DocxViewerWidget(
filePath: '/path/to/document.docx',
onSave: () async {
final path = await pickSaveLocation();
return path;
},
)
API Reference #
DocxViewerWidget #
| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| filePath | String | required | Path to .docx |
| config | DocxViewerConfig | const | Viewer config |
| onSave | Future<String?> Function()? | null | Save callback |
| onContentChanged | void Function(String)? | null | Change listener |
DocxViewerWidgetState Methods #
| Method | Returns | Description |
|--------|---------|-------------|
| save({String? outputPath}) | Future<String?> | Save to file |
| getDocxBytes() | Future<Uint8List?> | Get raw bytes |
| service | DocxService | Access service |
DocxService #
| Method | Returns | Description |
|--------|---------|-------------|
| loadFromPath(String) | Future
| loadFromBytes(Uint8List) | Future
| saveDocx({String?, String?}) | Future<String?> | Save .docx |
| getDocxBytes({String?}) | Future<Uint8List?> | Get bytes |
| hasDocument | bool | Doc is loaded |
| isModified | bool | Edits were made |
Platform Support #
| Platform | Status | Notes |
|----------|--------|-------|
| Android | Supported | Android WebView |
| iOS | Supported | WKWebView |
| macOS | Supported | WKWebView |
| Web | Not supported | Requires native WebView |
Troubleshooting #
Blank DOCX on share/save: Ensure you call getDocxBytes()
or save() AFTER the document has fully loaded. Check
service.hasDocument && service.html.isNotEmpty. The
widget’s getDocxBytes() includes automatic retry and
fallback to original bytes.
Images not appearing: Embedded images are preserved.
External URLs are not supported.
Large documents: Parsing runs in isolates. Very large
documents (>5MB) may take a few seconds to load.
License #
BSD-3-Clause. See LICENSE for details.
Author #
Muslim Bin Sohail — muslimbinsohail@gmail.com