Flutter电子书阅读插件epubber的使用

Flutter电子书阅读插件epubber的使用

本指南将详细介绍如何在Flutter项目中使用epubber插件来创建一个电子书阅读器。该插件基于epub包,能够在所有平台上使用Flutter小部件(而非原生视图)来渲染EPUB文档。

展示

展示

开始前的准备

首先,在你的Flutter项目中添加epubber依赖项:

dependencies:
  epubber: any

确保你已经配置好了pubspec.yaml文件,并运行flutter pub get以安装该依赖项。

使用示例

以下是一个完整的示例,展示了如何使用epubber插件来创建一个基本的EPUB电子书阅读器。

主要代码

import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:epubber/epubber.dart';
import 'package:flutter/services.dart' show rootBundle;

Future<Uint8List> _loadFromAssets(String assetName) async {
  final bytes = await rootBundle.load(assetName);
  return bytes.buffer.asUint8List();
}

EpubController _epubController;

@override
void initState() {
  _epubController = EpubController(
    // 加载文档
    document: EpubReader.readBook(_loadFromAssets('assets/book.epub')),
    // 设置起始点
    epubCfi: 'epubcfi(/6/6[chapter-2]!/4/2/1612)',
  );
  super.initState();
}

@override
Widget build(BuildContext context) => Scaffold(
  appBar: AppBar(
    // 显示当前章节名称
    title: EpubActualChapter(
      controller: _epubController,
      builder: (chapterValue) => Text(
        'Chapter ${chapterValue.chapter.Title ?? ''}',
        textAlign: TextAlign.start,
      ),
    ),
  ),
  // 显示目录
  drawer: Drawer(
    child: EpubReaderTableOfContents(
      controller: _epubController,
    ),
  ),
  // 显示EPUB文档
  body: EpubView(
    controller: _epubController,
  ),
);

详细代码解释

main.dart 文件

import 'dart:typed_data';

import 'package:epubber/epubber.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart' show SystemChrome, SystemUiOverlayStyle, rootBundle;

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
  @override
  void initState() {
    WidgetsBinding.instance.addObserver(this);
    super.initState();
  }

  @override
  void dispose() {
    WidgetsBinding.instance.removeObserver(this);
    super.dispose();
  }

  @override
  void didChangePlatformBrightness() {
    _setSystemUIOverlayStyle();
  }

  Brightness get platformBrightness =>
      MediaQueryData.fromWindow(WidgetsBinding.instance.window).platformBrightness;

  void _setSystemUIOverlayStyle() {
    if (platformBrightness == Brightness.light) {
      SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
        statusBarBrightness: Brightness.light,
        statusBarIconBrightness: Brightness.dark,
        systemNavigationBarColor: Colors.grey[50],
        systemNavigationBarIconBrightness: Brightness.dark,
      ));
    } else {
      SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
        statusBarBrightness: Brightness.dark,
        statusBarIconBrightness: Brightness.light,
        systemNavigationBarColor: Colors.grey[850],
        systemNavigationBarIconBrightness: Brightness.light,
      ));
    }
  }

  @override
  Widget build(BuildContext context) => MaterialApp(
        title: 'Epub demo',
        theme: ThemeData(
          primarySwatch: Colors.blue,
          brightness: Brightness.light,
        ),
        darkTheme: ThemeData(
          primarySwatch: Colors.blue,
          brightness: Brightness.dark,
        ),
        debugShowCheckedModeBanner: false,
        home: MyHomePage(),
      );
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  EpubController _epubReaderController;

  @override
  void initState() {
    final loadedBook = _loadFromAssets('assets/New-Findings-on-Shirdi-Sai-Baba.epub');
    _epubReaderController = EpubController(
      document: EpubReader.readBook(loadedBook),
      // document: EpubReader,
      // epubCfi: 'epubcfi(/6/26[id4]!/4/2/2[id4]/22)', // book.epub Chapter 3 paragraph 10
      // epubCfi: 'epubcfi(/6/6[chapter-2]!/4/2/1612)', // book_2.epub Chapter 16 paragraph 3
    );
    super.initState();
  }

  @override
  void dispose() {
    _epubReaderController.dispose();
    super.dispose();
  }

  Future<Uint8List> _loadFromAssets(String assetName) async {
    final bytes = await rootBundle.load(assetName);
    return bytes.buffer.asUint8List();
  }

  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          title: EpubActualChapter(
            controller: _epubReaderController,
            builder: (chapterValue) => Text(
              (chapterValue?.chapter?.Title?.trim() ?? '').replaceAll('\n', ''),
              textAlign: TextAlign.start,
            ),
          ),
          actions: [
            IconButton(
              icon: Icon(Icons.save_alt),
              color: Colors.white,
              onPressed: () => _showCurrentEpubCfi(context),
            ),
          ],
        ),
        drawer: Drawer(
          child: EpubReaderTableOfContents(controller: _epubReaderController),
        ),
        body: EpubView(
          controller: _epubReaderController,
          onDocumentLoaded: (document) {
            print('isLoaded: $document');
          },
          dividerBuilder: (_) => Divider(),
        ),
      );

  void _showCurrentEpubCfi(context) {
    final cfi = _epubReaderController.generateEpubCfi();

    if (cfi != null) {
      ScaffoldMessenger.of(context).showSnackBar(
        SnackBar(
          content: Text(cfi),
          action: SnackBarAction(
            label: 'GO',
            onPressed: () {
              _epubReaderController.gotoEpubCfi(cfi);
            },
          ),
        ),
      );
    }
  }
}

如何从上次阅读位置开始?

此方法允许你在章节内部保持精确的阅读位置:

_epubController = EpubController(
  // 初始化时使用EPUB CFI字符串以从上次位置打开书籍
  epubCfi: 'epubcfi(/6/6[chapter-2]!/4/2/1612)',
);

// 添加控制器
EpubView(
  controller: _epubController,
);

// 获取EPUB CFI字符串
// 例如输出 - epubcfi(/6/6[chapter-2]!/4/2/1612)
final cfi = _epubController.generateEpubCfi();

// 或者使用控制器进行导航
_epubController.gotoEpubCfi('epubcfi(/6/6[chapter-2]!/4/2/1612)');

更多关于Flutter电子书阅读插件epubber的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter电子书阅读插件epubber的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


关于Flutter电子书阅读插件epubber的使用,以下是一个基本的代码案例,展示了如何在Flutter应用中使用epubber插件来加载和显示EPUB电子书。请注意,这里假设你已经有一个Flutter开发环境,并且已经添加了epubber插件到你的pubspec.yaml文件中。

首先,确保你的pubspec.yaml文件中包含epubber插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  epubber: ^最新版本号  # 请替换为实际的最新版本号

然后,运行flutter pub get来安装依赖。

接下来,你可以创建一个简单的Flutter应用来展示如何使用epubber插件。以下是一个示例代码:

import 'package:flutter/material.dart';
import 'package:epubber/epubber.dart';
import 'dart:io';

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'EPUB Reader Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  EpubController? _controller;

  @override
  void initState() {
    super.initState();
    _loadEpub();
  }

  Future<void> _loadEpub() async {
    // 假设你有一个EPUB文件在应用的assets文件夹中
    // 你需要在pubspec.yaml中声明这个assets文件
    // assets:
    //   - assets/sample.epub
    final ByteData data = await rootBundle.load('assets/sample.epub');
    final Uint8List bytes = data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);

    // 使用epubber插件加载EPUB文件
    _controller = await EpubController.fromBytes(
      bytes,
      identifier: 'sample-epub',
      title: 'Sample EPUB',
      // 可以根据需要设置其他参数,如作者、封面等
    );

    // 设置当前章节(可选)
    _controller?.gotoChapter(0); // 跳转到第一章

    // 更新UI
    setState(() {});
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('EPUB Reader Demo'),
      ),
      body: _controller != null
          ? EpubView(
              controller: _controller!,
            )
          : Center(
              child: CircularProgressIndicator(),
            ),
    );
  }

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

在这个示例中,我们做了以下几件事:

  1. pubspec.yaml文件中添加了epubber插件的依赖。
  2. 创建了一个简单的Flutter应用,其中包含一个MyHomePage页面。
  3. MyHomePage页面的initState方法中,使用rootBundle.load方法从assets文件夹中加载EPUB文件,并将其转换为Uint8List
  4. 使用EpubController.fromBytes方法创建一个EpubController实例,用于管理EPUB文件的加载和显示。
  5. 使用EpubView小部件来显示EPUB内容。在_controller不为空之前,显示一个进度指示器。
  6. dispose方法中释放EpubController实例,以避免内存泄漏。

请注意,这只是一个基本的示例,实际使用中你可能需要根据具体需求进行更多的配置和优化,比如添加导航栏以在章节之间切换、处理错误情况、优化UI布局等。

回到顶部