You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android PDF阅读器开发:实现History Fragment与Document Fragment间PDF阅读页码双向同步

我来帮你解决这个PDF页码双向同步的问题,核心问题出在你当前的页码存储逻辑上——现在的实现既做不到跨Activity共享数据,也没有区分不同的PDF文件,自然无法实现双向同步。

问题根源分析

  1. SharedPreferences作用域错误:你用的getPreferences(MODE_PRIVATE)是当前Activity的私有存储,ViewPdf和ViewHistoryPdf的存储完全独立,两边的页码数据根本互通不了。
  2. 未区分不同PDF文件:所有PDF的页码都存在同一个"page"键下,打开不同PDF时会互相覆盖,导致页码混乱。

解决方案步骤

我们需要做两个核心修改:用全局SharedPreferences统一存储所有PDF的阅读进度,并且用PDF文件的绝对路径作为每个文件的唯一标识,确保不同PDF的页码不会互相干扰。同时要保证页面离开时自动保存当前页码。

修改后的代码实现

1. 更新ViewPdf.java

public class ViewPdf extends AppCompatActivity {
    public static PDFView pdfView;
    TextView textView;
    File currentPdfFile;
    SharedPreferences pageRecordsPrefs;
    SharedPreferences.Editor editor;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_pdf);

        pdfView = findViewById(R.id.pdfView);
        textView = findViewById(R.id.pagenumber);
        // 全局SharedPreferences,所有Activity共享
        pageRecordsPrefs = getSharedPreferences("PDF_PAGE_RECORDS", MODE_PRIVATE);
        editor = pageRecordsPrefs.edit();

        // 获取要打开的PDF文件
        int position = getIntent().getIntExtra("Position", -1);
        if (position != -1) {
            currentPdfFile = DocumentsFragment.pdf.get(position);
            loadPdfWithSavedPage(currentPdfFile);
        }
    }

    private void loadPdfWithSavedPage(File pdfFile) {
        // 用文件绝对路径作为唯一键,默认加载第0页(第一页)
        String pageKey = "page_" + pdfFile.getAbsolutePath();
        int savedPage = pageRecordsPrefs.getInt(pageKey, 0);

        pdfView.fromFile(pdfFile)
                .enableAnnotationRendering(true)
                .defaultPage(savedPage)
                .swipeHorizontal(true)
                .nightMode(true)
                .fitEachPage(true)
                .onPageChange((page, pageCount) -> {
                    textView.setText(String.valueOf(page + 1) + "/" + pageCount);
                    // 实时保存页码(也可以在onPause时统一保存)
                    editor.putInt(pageKey, page);
                    editor.apply();
                })
                .pageSnap(true)
                .pageFling(true)
                .autoSpacing(false)
                .spacing(12)
                .enableAntialiasing(true)
                .pageFitPolicy(FitPolicy.BOTH)
                .load();
    }

    @Override
    protected void onPause() {
        super.onPause();
        // 页面离开时再次确认保存,防止实时保存遗漏
        if (currentPdfFile != null && pdfView != null) {
            String pageKey = "page_" + currentPdfFile.getAbsolutePath();
            editor.putInt(pageKey, pdfView.getCurrentPage());
            editor.apply();
        }
    }
}

2. 更新ViewHistoryPdf.java

public class ViewHistoryPdf extends AppCompatActivity {
    PDFView pdfView;
    TextView textView;
    File currentPdfFile;
    SharedPreferences pageRecordsPrefs;
    SharedPreferences.Editor editor;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_pdf);

        pdfView = findViewById(R.id.pdfView);
        textView = findViewById(R.id.pagenumber);
        // 和ViewPdf用同一个全局SharedPreferences
        pageRecordsPrefs = getSharedPreferences("PDF_PAGE_RECORDS", MODE_PRIVATE);
        editor = pageRecordsPrefs.edit();

        // 获取要打开的历史PDF文件
        int historyPosition = getIntent().getIntExtra("History", -1);
        if (historyPosition != -1) {
            currentPdfFile = HistoryFragment.pdfHistory.get(historyPosition);
            loadPdfWithSavedPage(currentPdfFile);
        }
    }

    private void loadPdfWithSavedPage(File pdfFile) {
        String pageKey = "page_" + pdfFile.getAbsolutePath();
        int savedPage = pageRecordsPrefs.getInt(pageKey, 0);

        pdfView.fromFile(pdfFile)
                .enableAnnotationRendering(true)
                .defaultPage(savedPage)
                .swipeHorizontal(true)
                .nightMode(true)
                .fitEachPage(true)
                .onPageChange((page, pageCount) -> {
                    textView.setText(String.valueOf(page + 1) + "/" + pageCount);
                    editor.putInt(pageKey, page);
                    editor.apply();
                })
                .pageSnap(true)
                .pageFling(true)
                .autoSpacing(false)
                .spacing(12)
                .enableAntialiasing(true)
                .pageFitPolicy(FitPolicy.BOTH)
                .load();
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (currentPdfFile != null && pdfView != null) {
            String pageKey = "page_" + currentPdfFile.getAbsolutePath();
            editor.putInt(pageKey, pdfView.getCurrentPage());
            editor.apply();
        }
    }
}

额外优化建议

为了避免代码重复,你可以把PDF加载和页码处理的逻辑抽成工具类,比如:

public class PdfViewerHelper {
    public static void loadPdf(PDFView pdfView, File pdfFile, TextView pageText, SharedPreferences prefs) {
        String pageKey = "page_" + pdfFile.getAbsolutePath();
        int savedPage = prefs.getInt(pageKey, 0);
        SharedPreferences.Editor editor = prefs.edit();

        pdfView.fromFile(pdfFile)
                .enableAnnotationRendering(true)
                .defaultPage(savedPage)
                .swipeHorizontal(true)
                .nightMode(true)
                .fitEachPage(true)
                .onPageChange((page, pageCount) -> {
                    pageText.setText(String.valueOf(page + 1) + "/" + pageCount);
                    editor.putInt(pageKey, page);
                    editor.apply();
                })
                .pageSnap(true)
                .pageFling(true)
                .autoSpacing(false)
                .spacing(12)
                .enableAntialiasing(true)
                .pageFitPolicy(FitPolicy.BOTH)
                .load();
    }
}

这样两个Activity里只需要一行代码就能完成PDF加载,代码会更简洁易维护。

内容的提问来源于stack exchange,提问作者Knowledge hub

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 13:08:15