首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Android MuPDF 橫屏顯示 PDF 縮放異常:寬度自適應與手勢縮放完整解決方案

     編輯:程式設計綜合問答

問題現象

使用 MuPDF 庫橫屏閱讀 PDF 時,頁面被縮小顯示整頁,而非寬度自適應螢幕。期望效果:橫屏時頁面寬度撐滿螢幕,高度可垂直滑動,支援雙指縮放。

核心原因

MuPDF 默認渲染邏輯為 FitPage(整頁適應),未根據螢幕方向動態切換渲染模式。需手動計算縮放矩陣實現 FitWidth(寬度適應)。

解決方案:自定義 MuPDFView 實現 FitWidth + 手勢縮放

1. 核心渲染邏輯(Kotlin)

class CustomMuPDFView(context: Context, attrs: AttributeSet) : MuPDFView(context, attrs) {

    private var fitWidth = false
    
    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        super.onLayout(changed, l, t, r, b)
        if (changed || !fitWidth) {
            applyFitWidth()
        }
    }
    
    private fun applyFitWidth() {
        val pageWidth = getPageWidth(0).toFloat()
        val viewWidth = width.toFloat()
        if (pageWidth > 0) {
            val scale = viewWidth / pageWidth
            // 設置縮放矩陣:寬度適應,居中顯示
            val matrix = Matrix().apply {
                setScale(scale, scale)
                postTranslate(0f, 0f)  // 垂直方向不偏移,允許滑動
            }
            setDisplayMatrix(matrix)
            fitWidth = true
        }
    }
    
    // 暴露方法供 Activity/Fragment 在旋轉時調用
    fun refreshFitWidth() {
        fitWidth = false
        applyFitWidth()
    }
}

2. 手勢縮放支援(雙指捏合)

private val scaleDetector = ScaleGestureDetector(context, object : ScaleGestureDetector.SimpleOnScaleGestureListener() {
    override fun onScale(detector: ScaleGestureDetector): Boolean {
        val matrix = getDisplayMatrix()
        val scaleFactor = detector.scaleFactor
        
        // 限制縮放範圍 0.5x ~ 3.0x
        val currentScale = getCurrentScale(matrix)
        val newScale = (currentScale * scaleFactor).coerceIn(0.5f, 3.0f)
        val finalFactor = newScale / currentScale
        
        matrix.postScale(finalFactor, finalFactor, detector.focusX, detector.focusY)
        setDisplayMatrix(matrix)
        return true
    }
})

override fun onTouchEvent(ev: MotionEvent): Boolean {
    scaleDetector.onTouchEvent(ev)
    return super.onTouchEvent(ev)
}

3. Activity 中處理旋轉

override fun onConfigurationChanged(newConfig: Configuration) {
    super.onConfigurationChanged(newConfig)
    muPDFView.refreshFitWidth()  // 旋轉後重新計算 FitWidth
}

別忘在 `AndroidManifest.xml` 中聲明:

<activity
    android:name=".PdfReaderActivity"
    android:configChanges="orientation|screenSize|screenLayout"
    android:windowSoftInputMode="adjustResize">

替代方案:使用 PdfRenderer (API 21+) 或第三方庫

方案優點缺點
MuPDF 自定義功能全、渲染快、支援註釋體積大、需 NDK、授權 GPL
Android PdfRenderer系統級、無依賴、體積小僅支援 API 21+、功能較簡單
PDFViewPager / pdfviewer封裝好、易用依賴 MuPDF 或 PdfRenderer、定制難

總結

MuPDF 橫屏寬度自適應關鍵在於根據 View 寬度動態計算縮放矩陣並應用,而非依賴庫默認行為。結合 `ScaleGestureDetector` 即可實現完整的「寬度適應 + 垂直滑動 + 雙指縮放」閱讀體驗。若項目允許,API 21+ 可考慮系統 `PdfRenderer` 簡化依賴。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved