Android App开发手机阅读中PDF文件渲染器的讲解及使用(附源码 简单易懂)

简介: Android App开发手机阅读中PDF文件渲染器的讲解及使用(附源码 简单易懂)

需要源码和图片集请点赞关注收藏后评论区留言~~~

一、PDF文件渲染器

Android集成了PDF的渲染操作,从很大程度上方便了开发者,这个PDF文件渲染器便是PdfRenderer。渲染器允许从存储卡读取PDF文件

打开PDF文件只是第一步,接下来使用PdfRenderer工具加载PDF文件,并进行相关的处理操作 下面是PdfRenderer类的常用方法

构造方法:从ParcelFileDescriptor对象构造一个PdeRenderer实例

getPageCount 获取PDF文件的页数

openPage 打开PDF文件的指定页面 返回一个PdeRenderer.Page对象

close 关闭PDF文件

从上面列出的方法可以看到,PDF渲染器只提供了对整个PDF文件的管理操作,具体的页面处理得由PdfRenderer.Page对象完成 下面是Page类得常用方法

getIndex 获取该页得页码

getWidth 获取宽度

getHeight 获取高度

render 渲染该页面内容 并将渲染结果写入一个位图对象

close 关闭该页面

PDF渲染器支持把一个PDF文件转成若干图片。开发者可以将这些图片展示在屏幕上 解析效果如下

此处最好连接真机测试 这样可以从存储卡上读取PDF文件

代码如下

Java类

package com.example.ebook;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.viewpager.widget.PagerTabStrip;
import androidx.viewpager.widget.ViewPager;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuItem;
import com.example.ebook.adapter.PdfPageAdapter;
import com.example.ebook.dao.BookDao;
import com.example.ebook.entity.BookInfo;
import com.example.ebook.util.AssetsUtil;
import java.util.ArrayList;
import java.util.List;
public class PdfRenderActivity extends AppCompatActivity {
    private final static String TAG = "PdfRenderActivity";
    private List<String> mPathList = new ArrayList<>(); // 图片路径列表
    private String mFileName = "tangshi.pdf"; // 演示文件的名称
    private ViewPager vp_content; // 声明一个翻页视图对象
    private BookDao bookDao; // 声明一个书籍的持久化对象
    private ProgressDialog mDialog; // 声明一个进度对话框对象
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_pdf_render);
        initView(); // 初始化视图
        // 从App实例中获取唯一的书籍持久化对象
        bookDao = MainApplication.getInstance().getBookDB().bookDao();
        // 弹出进度对话框
        mDialog = ProgressDialog.show(this, "请稍候", "正在努力加载");
        new Thread(() -> importPDF()).start(); // 启动pdf文件的导入线程
    }
    // 初始化视图
    private void initView() {
        String title = "";
        // 从前个页面传来的数据中获取书籍的标题和文件名称
        if (getIntent().getExtras()!=null && !getIntent().getExtras().isEmpty()) {
            title = getIntent().getStringExtra("title");
            mFileName = getIntent().getStringExtra("file_name");
        }
        Toolbar tl_head = findViewById(R.id.tl_head);
        tl_head.setTitle(!TextUtils.isEmpty(title) ? title : mFileName);
        setSupportActionBar(tl_head); // 替换系统自带的ActionBar
        // 设置工具栏左侧导航图标的点击监听器
        tl_head.setNavigationOnClickListener(view -> finish());
        vp_content = findViewById(R.id.vp_content);
        PagerTabStrip pts_tab = findViewById(R.id.pts_tab);
        // 设置翻页标题栏的文本大小
        pts_tab.setTextSize(TypedValue.COMPLEX_UNIT_SP, 17);
    }
    // 从指定的资产文件导入pdf文件
    private void importPDF() {
        mPathList = AssetsUtil.getPathListFromPdf(this, mFileName);
        Log.d(TAG, "mPathList.size="+mPathList.size());
        BookInfo book = bookDao.queryBookByName(mFileName);
        if (book != null) {
            book.setPageCount(mPathList.size());
            bookDao.updateBook(book); // 更新数据库中该书籍记录的总页数
        }
        // 回到主线程显示导入后的pdf各页面
        runOnUiThread(() -> {
            PdfPageAdapter adapter = new PdfPageAdapter(getSupportFragmentManager(), mPathList);
            vp_content.setAdapter(adapter);
            if (mDialog != null && mDialog.isShowing()) {
                mDialog.dismiss(); // 关闭进度对话框
            }
        });
    }
    // 在创建选项菜单时调用
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_book, menu);
        return true;
    }
    // 在选中菜单项时调用
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == R.id.menu_slide) { // 点击了“平滑翻页”
            Intent intent = new Intent(this, PdfSlideActivity.class);
            intent.putExtra("file_name", mFileName);
            startActivity(intent);
        } else if (item.getItemId() == R.id.menu_curve) { // 点击了“卷曲翻页”
            Intent intent = new Intent(this, PdfCurveActivity.class);
            intent.putExtra("file_name", mFileName);
            startActivity(intent);
        } else if (item.getItemId() == R.id.menu_opengl) { // 点击了“OpenGL翻页”
            Intent intent = new Intent(this, PdfOpenglActivity.class);
            intent.putExtra("file_name", mFileName);
            startActivity(intent);
        }
        return super.onOptionsItemSelected(item);
    }
}

XML文件

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <androidx.appcompat.widget.Toolbar
        android:id="@+id/tl_head"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:background="@color/blue_light"
        app:navigationIcon="@drawable/icon_back" />
    <androidx.viewpager.widget.ViewPager
        android:id="@+id/vp_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <androidx.viewpager.widget.PagerTabStrip
            android:id="@+id/pts_tab"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    </androidx.viewpager.widget.ViewPager>
</LinearLayout>

创作不易 觉得有帮助请 点赞关注收藏~~~

相关文章
|
机器学习/深度学习 存储 人工智能
MNN-LLM App:在手机上离线运行大模型,阿里巴巴开源基于 MNN-LLM 框架开发的手机 AI 助手应用
MNN-LLM App 是阿里巴巴基于 MNN-LLM 框架开发的 Android 应用,支持多模态交互、多种主流模型选择、离线运行及性能优化。
16660 81
MNN-LLM App:在手机上离线运行大模型,阿里巴巴开源基于 MNN-LLM 框架开发的手机 AI 助手应用
|
Dart 前端开发
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
568 75
【05】flutter完成注册页面完善样式bug-增加自定义可复用组件widgets-严格规划文件和目录结构-规范入口文件-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程-商业应用级实战开发-优雅草央千澈
|
存储 算法 API
【01】整体试验思路,如何在有UID的情况下获得用户手机号信息,python开发之理论研究试验,如何通过抖音视频下方的用户的UID获得抖音用户的手机号-本系列文章仅供学习研究-禁止用于任何商业用途-仅供学习交流-优雅草卓伊凡
【01】整体试验思路,如何在有UID的情况下获得用户手机号信息,python开发之理论研究试验,如何通过抖音视频下方的用户的UID获得抖音用户的手机号-本系列文章仅供学习研究-禁止用于任何商业用途-仅供学习交流-优雅草卓伊凡
4278 82
|
安全 测试技术 开发者
银行转账模拟器手机版app, 银行转账凭证生成器app,用autojs实现效果【逼真效果】
本内容展示了一套基于Auto.js的银行APP自动化测试脚本和框架,用于学习和研究移动应用测试技术。脚本涵盖登录、转账等功能测试
|
11月前
|
编解码 数据安全/隐私保护
手机录制脚本自动执行, 免root屏幕录制脚本,自动脚本精灵app【autojs】
自动创建保存目录确保路径存在 动态生成带时间戳的文件名避免重复
|
C++ Windows
【Function App】本地通过VS Code调试Function时候遇见无法加载文件错误Microsoft.Extensions.Diagnostics.Abstractions
在使用 VS Code 调试 Azure Functions 时,执行 `func host start` 可能因版本冲突报错。错误信息显示 Rpc Initialization Service 启动失败,可能是由于缺少文件或组件导致。解决方法包括:1) 使用 npm 卸载并重新安装 Azure Functions Core Tools;2) 若问题未解决,重新下载安装包(如 func-cli-x64.msi)修复旧版本工具;3) 退出并重启 VS Code,重新加载项目即可恢复正常运行。参考资料链接提供了更多背景信息。
500 1
|
XML 搜索推荐 Android开发
Android改变进度条控件progressbar的样式(根据源码修改)
本文介绍了如何基于Android源码自定义ProgressBar样式。首先分析了系统源码中ProgressBar样式的定义,发现其依赖一张旋转图片实现动画效果。接着分两步指导开发者实现自定义:1) 模仿源码创建一个旋转动画XML文件(放置在drawable文件夹),修改图片为自定义样式;2) 在UI控件中通过`indeterminateDrawable`属性应用该动画。最终实现简单且个性化的ProgressBar效果,附带效果图展示。
716 2
|
存储 人工智能 编译器
【03】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-测试hello word效果-虚拟华为手机真机环境调试-为DevEco Studio编译器安装中文插件-测试写一个滑动块效果-介绍诸如ohos.ui等依赖库-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
【03】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-测试hello word效果-虚拟华为手机真机环境调试-为DevEco Studio编译器安装中文插件-测试写一个滑动块效果-介绍诸如ohos.ui等依赖库-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
1115 11
【03】鸿蒙实战应用开发-华为鸿蒙纯血操作系统Harmony OS NEXT-测试hello word效果-虚拟华为手机真机环境调试-为DevEco Studio编译器安装中文插件-测试写一个滑动块效果-介绍诸如ohos.ui等依赖库-全过程实战项目分享-从零开发到上线-优雅草卓伊凡
|
NoSQL 应用服务中间件 PHP
布谷一对一直播源码android版环境配置流程及功能明细
部署需基于 CentOS 7.9 系统,硬盘不低于 40G,使用宝塔面板安装环境,包括 PHP 7.3(含 Redis、Fileinfo 扩展)、Nginx、MySQL 5.6、Redis 和最新 Composer。Swoole 扩展需按步骤配置。2021.08.05 后部署需将站点目录设为 public 并用 ThinkPHP 伪静态。开发环境建议 Windows 操作系统与最新 Android Studio,基础配置涉及 APP 名称修改、接口域名更换、包名调整及第三方登录分享(如 QQ、微信)的配置,同时需完成阿里云与腾讯云相关设置。
|
存储 API 数据安全/隐私保护
【02】整体试验思路,在这之前我们发现sec_uid,sec_uid是什么和uid的关系又是什么?相互如何转换?python开发之理论研究试验,如何通过抖音视频下方的用户的UID获得抖音用户的手机号-本系列文章仅供学习研究-禁止用于任何商业用途-仅供学习交流-优雅草卓伊凡
【02】整体试验思路,在这之前我们发现sec_uid,sec_uid是什么和uid的关系又是什么?相互如何转换?python开发之理论研究试验,如何通过抖音视频下方的用户的UID获得抖音用户的手机号-本系列文章仅供学习研究-禁止用于任何商业用途-仅供学习交流-优雅草卓伊凡
3296 6

热门文章

最新文章