docx_file_viewer 1.0.1 copy "docx_file_viewer: ^1.0.1" to clipboard
docx_file_viewer: ^1.0.1 copied to clipboard

A Flutter package for rendering DOCX files with native widgets. View, zoom, search, and interact with Word documents.

example/lib/main.dart

import 'dart:io';

import 'package:docx_file_viewer/docx_file_viewer.dart';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() {
  runApp(const DocxViewerExampleApp());
}

class DocxViewerExampleApp extends StatelessWidget {
  const DocxViewerExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'DOCX Viewer Example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
        useMaterial3: true,
      ),
      darkTheme: ThemeData.dark(useMaterial3: true),
      home: const HomeScreen(),
    );
  }
}

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  File? _selectedFile;
  Uint8List? _demoBytes;
  bool _enableZoom = true;
  bool _darkMode = false;
  final bool _isLoading = false;
  String? _errorMessage;

  // Search state
  late DocxSearchController _searchController;
  final TextEditingController _searchTextController = TextEditingController();
  bool _isSearchActive = false;

  @override
  void initState() {
    super.initState();
    _searchController = DocxSearchController();
    _searchController.addListener(_onSearchChanged);
  }

  @override
  void dispose() {
    _searchController.removeListener(_onSearchChanged);
    _searchController.dispose();
    _searchTextController.dispose();
    super.dispose();
  }

  void _onSearchChanged() {
    // Rebuild to update match counts
    if (mounted) setState(() {});
  }

  Future<void> _pickFile() async {
    final result = await FilePicker.platform.pickFiles(
      type: FileType.custom,
      allowedExtensions: ['docx'],
    );

    if (result != null && result.files.single.path != null) {
      setState(() {
        _selectedFile = File(result.files.single.path!);
        _demoBytes = null;
        _errorMessage = null;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: _buildAppBar(),
      body: _buildBody(),
      floatingActionButton: FloatingActionButton(
        onPressed: _pickFile,
        child: const Icon(Icons.folder_open),
      ),
    );
  }

  PreferredSizeWidget _buildAppBar() {
    if (_isSearchActive) {
      return AppBar(
        leading: IconButton(
          icon: const Icon(Icons.arrow_back),
          onPressed: () {
            setState(() {
              _isSearchActive = false;
              _searchController.clear();
              _searchTextController.clear();
            });
          },
        ),
        title: TextField(
          controller: _searchTextController,
          autofocus: true,
          decoration: const InputDecoration(
            hintText: 'Search text...',
            border: InputBorder.none,
          ),
          onSubmitted: (value) => _searchController.search(value),
          onChanged: (value) => _searchController.search(value),
          textInputAction: TextInputAction.search,
        ),
        actions: [
          // Match Counter
          if (_searchController.matchCount > 0)
            Center(
              child: Padding(
                padding: const EdgeInsets.symmetric(horizontal: 8.0),
                child: Text(
                  '${_searchController.currentMatchIndex + 1}/${_searchController.matchCount}',
                  style: const TextStyle(fontSize: 16),
                ),
              ),
            ),
          // Navigation Buttons
          IconButton(
            icon: const Icon(Icons.expand_less),
            onPressed: _searchController.previousMatch,
            tooltip: 'Previous',
          ),
          IconButton(
            icon: const Icon(Icons.expand_more),
            onPressed: _searchController.nextMatch,
            tooltip: 'Next',
          ),
        ],
      );
    }

    return AppBar(
      title: const Text('DOCX Viewer'),
      actions: [
        IconButton(
          icon: const Icon(Icons.search),
          onPressed: () {
            setState(() {
              _isSearchActive = true;
            });
          },
          tooltip: 'Search',
        ),
        IconButton(
          icon: Icon(_darkMode ? Icons.light_mode : Icons.dark_mode),
          onPressed: () => setState(() => _darkMode = !_darkMode),
          tooltip: 'Toggle theme',
        ),
        PopupMenuButton<String>(
          icon: const Icon(Icons.settings),
          onSelected: (value) {
            setState(() {
              if (value == 'zoom') _enableZoom = !_enableZoom;
            });
          },
          itemBuilder: (context) => [
            CheckedPopupMenuItem(
              value: 'zoom',
              checked: _enableZoom,
              child: const Text('Enable Zoom'),
            ),
          ],
        ),
      ],
    );
  }

  Widget _buildBody() {
    if (_isLoading) {
      return const Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            CircularProgressIndicator(),
            SizedBox(height: 16),
            Text('Loading demo document...'),
          ],
        ),
      );
    }

    if (_selectedFile == null && _demoBytes == null) {
      return Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            const Icon(Icons.description, size: 80, color: Colors.grey),
            const SizedBox(height: 16),
            if (_errorMessage != null) ...[
              Text(
                _errorMessage!,
                style: const TextStyle(fontSize: 14, color: Colors.red),
                textAlign: TextAlign.center,
              ),
              const SizedBox(height: 16),
            ],
            const Text(
              'No document selected',
              style: TextStyle(fontSize: 18, color: Colors.grey),
            ),
            const SizedBox(height: 24),
            ElevatedButton.icon(
              onPressed: _pickFile,
              icon: const Icon(Icons.folder_open),
              label: const Text('Open DOCX File'),
            ),
          ],
        ),
      );
    }

    return DocxView(
      file: _selectedFile,
      bytes: _demoBytes,
      config: DocxViewConfig(
        enableSearch: true, // Always enable logic, we control interaction
        enableZoom: _enableZoom,
        theme: _darkMode ? DocxViewTheme.dark() : DocxViewTheme.light(),
        backgroundColor: _darkMode ? const Color(0xFF1E1E1E) : Colors.white,
        showDebugInfo: true,
      ),
      searchController: _searchController, // Pass explicit controller
    );
  }
}
12
likes
160
points
927
downloads
screenshot

Publisher

verified publisheralihassan143cool.blogspot.com

Weekly Downloads

A Flutter package for rendering DOCX files with native widgets. View, zoom, search, and interact with Word documents.

Homepage
Repository (GitHub)
View/report issues

Topics

#docx #word #viewer #document #office

Documentation

API reference

License

Apache-2.0 (license)

Dependencies

docx_creator, flutter, url_launcher

More

Packages that depend on docx_file_viewer