flutter_epub_viewer_kit 0.0.4 copy "flutter_epub_viewer_kit: ^0.0.4" to clipboard
flutter_epub_viewer_kit: ^0.0.4 copied to clipboard

A customizable EPUB reader widget for Flutter. Supports iOS, Android, and Web platforms with features like pagination, scrolling, bookmarks, and customizable themes.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter_epub_viewer_kit/flutter_epub_viewer_kit.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'EPUB Reader Example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
        useMaterial3: true,
      ),
      home: const HomePage(),
    );
  }
}

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

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  late final EpubReaderController _controller;

  @override
  void initState() {
    super.initState();
    _controller = EpubReaderController(
      // Resume reading position (0.0 ~ 1.0)
      // You can load this from your own storage (e.g., database)
      initialProgress: 0.0,

      // Initial bookmarks (load from your storage if needed)
      initialBookmarks: [],

      // Called when reading position changes
      onPositionChanged: (position) {
        debugPrint(
          'Position: page ${position.pageIndex + 1}/${position.totalPages}, '
          'progress: ${(position.progress * 100).toStringAsFixed(1)}%',
        );
        // You can save position.progress to your database here
      },

      // Called when settings change (settings are auto-saved to device)
      onSettingsChanged: (settings) {
        debugPrint(
          'Settings changed: fontSize=${settings.fontSize}, '
          'isPageMode=${settings.isPageMode}',
        );
      },

      // Called when bookmark is added
      onBookmarkAdded: (bookmark) {
        debugPrint('Bookmark added: page ${bookmark.pageIndex + 1}');
        setState(() {});
        // Save bookmark to your database here
      },

      // Called when bookmark is removed
      onBookmarkRemoved: (bookmark) {
        debugPrint('Bookmark removed: page ${bookmark.pageIndex + 1}');
        setState(() {});
        // Remove bookmark from your database here
      },
    );
    _controller.addListener(_onControllerChanged);
  }

  void _onControllerChanged() {
    if (mounted) setState(() {});
  }

  @override
  void dispose() {
    _controller.removeListener(_onControllerChanged);
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return EpubReaderWidget(
      source: const EpubSourceAsset('assets/example.epub'),
      controller: _controller,
      // Settings are automatically saved to device storage with this key
      // Set to null to disable auto-save
      settingsStorageKey: 'epub_reader_settings',
      // Custom top/bottom bars
      showTopBar: true,
      showBottomBar: true,
      topBarBuilder: (context, settings) => _buildTopBar(settings),
      bottomBarBuilder: (context, settings) => _buildBottomBar(settings),
      watermark: _buildWatermark(),
      onPageChanged: (current, total) {
        debugPrint('Page: $current / $total');
      },
      onBookLoaded: (title, author) {
        debugPrint('Book loaded: $title by $author');
      },
      onError: (error) {
        ScaffoldMessenger.of(
          context,
        ).showSnackBar(SnackBar(content: Text('Error: $error')));
      },
    );
  }

  PreferredSizeWidget _buildTopBar(ReaderSettings settings) {
    final isBookmarked = _controller.isCurrentPageBookmarked;

    return PreferredSize(
      preferredSize: const Size.fromHeight(kToolbarHeight),
      child: Material(
        color: settings.backgroundColor.withValues(alpha: 0.95),
        elevation: 4,
        child: SafeArea(
          bottom: false,
          child: Container(
            height: kToolbarHeight,
            padding: const EdgeInsets.symmetric(horizontal: 8),
            child: Row(
              children: [
                IconButton(
                  icon: Icon(Icons.arrow_back, color: settings.textColor),
                  onPressed: () => Navigator.maybePop(context),
                ),
                Expanded(
                  child: Text(
                    'EPUB Reader',
                    style: TextStyle(
                      color: settings.textColor,
                      fontSize: 16,
                      fontWeight: FontWeight.w500,
                    ),
                  ),
                ),
                // Bookmark toggle
                IconButton(
                  icon: Icon(
                    isBookmarked ? Icons.bookmark : Icons.bookmark_border,
                    color: isBookmarked ? Colors.amber : settings.textColor,
                  ),
                  onPressed: () => _controller.toggleBookmark(),
                ),
                // Bookmarks list
                IconButton(
                  icon: Icon(Icons.list, color: settings.textColor),
                  onPressed: _showBookmarksList,
                ),
                // Settings (uses built-in panel)
                IconButton(
                  icon: Icon(Icons.settings, color: settings.textColor),
                  onPressed: () => _controller.showSettings(),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  Widget _buildBottomBar(ReaderSettings settings) {
    final currentPage = _controller.currentPage + 1;
    final totalPages = _controller.totalPages;
    final progress = _controller.progress;

    return Material(
      color: settings.backgroundColor.withValues(alpha: 0.95),
      elevation: 4,
      child: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            // Progress bar
            LinearProgressIndicator(
              value: progress,
              backgroundColor: settings.textColor.withValues(alpha: 0.2),
              valueColor: AlwaysStoppedAnimation<Color>(
                settings.textColor.withValues(alpha: 0.6),
              ),
            ),
            const SizedBox(height: 8),
            // Page info and navigation
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                Text(
                  '$currentPage / $totalPages (${(progress * 100).toStringAsFixed(1)}%)',
                  style: TextStyle(
                    color: settings.textColor.withValues(alpha: 0.7),
                    fontSize: 12,
                  ),
                ),
                Row(
                  children: [
                    IconButton(
                      icon: Icon(Icons.chevron_left, color: settings.textColor),
                      onPressed: () => _controller.previousPage(),
                    ),
                    IconButton(
                      icon: Icon(
                        Icons.chevron_right,
                        color: settings.textColor,
                      ),
                      onPressed: () => _controller.nextPage(),
                    ),
                  ],
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }

  void _showBookmarksList() {
    final bookmarks = _controller.bookmarks;

    showModalBottomSheet(
      context: context,
      builder: (context) {
        if (bookmarks.isEmpty) {
          return const SizedBox(
            height: 200,
            child: Center(child: Text('No bookmarks yet')),
          );
        }

        return ListView.builder(
          shrinkWrap: true,
          itemCount: bookmarks.length,
          itemBuilder: (context, index) {
            final bookmark = bookmarks[index];
            return ListTile(
              leading: const Icon(Icons.bookmark),
              title: Text('Page ${bookmark.pageIndex + 1}'),
              subtitle: bookmark.excerpt != null
                  ? Text(
                      bookmark.excerpt!,
                      maxLines: 2,
                      overflow: TextOverflow.ellipsis,
                    )
                  : null,
              trailing: IconButton(
                icon: const Icon(Icons.delete_outline),
                onPressed: () {
                  _controller.removeBookmark(bookmark);
                  Navigator.pop(context);
                  _showBookmarksList();
                },
              ),
              onTap: () {
                _controller.goToBookmark(bookmark);
                Navigator.pop(context);
              },
            );
          },
        );
      },
    );
  }

  Widget _buildWatermark() {
    return Opacity(
      opacity: 0.08,
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          Icon(
            Icons.menu_book_outlined,
            size: 160,
            color: Colors.grey.shade600,
          ),
          const SizedBox(height: 12),
          Text(
            'Flutter EPUB Viewer',
            style: TextStyle(
              fontSize: 20,
              fontWeight: FontWeight.w600,
              color: Colors.grey.shade600,
              letterSpacing: 1.1,
            ),
          ),
        ],
      ),
    );
  }
}
2
likes
155
points
180
downloads

Publisher

verified publisherpbbz.co.kr

Weekly Downloads

A customizable EPUB reader widget for Flutter. Supports iOS, Android, and Web platforms with features like pagination, scrolling, bookmarks, and customizable themes.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

epub_view, epubx, flutter, flutter_html, google_fonts, html, http, scrollable_positioned_list, shared_preferences

More

Packages that depend on flutter_epub_viewer_kit