Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I use horizontal viewpage, when Defaultpage is not 0,pdf can not be displayed in the center,and It's centered when touches it. #674

Closed
kzqsky opened this issue Sep 4, 2018 · 6 comments

Comments

@kzqsky
Copy link

kzqsky commented Sep 4, 2018

here code:
pdfView.fromFile(new File(pdfPath))
.defaultPage(index)
.swipeHorizontal(true)
.enableSwipe(true)
.enableDoubletap(true)
.autoSpacing(true)
.pageFling(true)
.pageSnap(true)
.pageFitPolicy(FitPolicy.BOTH)

            .enableAnnotationRendering(true)
            .enableAntialiasing(true)
            .onPageChange(this).onLoad(this).onPageError(this)
            .load();

device-2018-09-04-205521

How do I fix it? Thank you so much

@arthurdick
Copy link

I have observed this issue as well. I believe the root cause is in the PDFView.jumpTo function. The calculated offset value should be accounting for the page spacing based on the snap policy.

The PDFView.onSizeChanged function has a similar issue, where the offset value needs to account for the snap policy.

@Flamedek ideas for how this would best be resolved?

@arthurdick
Copy link

If it is helpful, my workaround is to extend the PDFView, and override the jumpTo function

    /* hacky workaround, jump to centre of page */
    @Override
    public void jumpTo(int page, boolean withAnimation) {
        if (pdfFile == null) {
            return;
        }

        // assumes swiping horizontal and snapping centre

        page = pdfFile.determineValidPageNumberFrom(page);
        float offset = page == 0 ? 0 : -pdfFile.getPageOffset(page, getZoom());
        offset += pdfFile.getPageSpacing(page, getZoom()) / 2f;

        if (withAnimation) {
            animationManagerRef.startXAnimation(getCurrentXOffset(), offset);
        } else {
            moveTo(offset, getCurrentYOffset());
        }

        showPage(page);
    }

@Flamedek
Copy link
Contributor

@arthurdick Thank you for investigating. This actually looks good and it's true that the calculated offset is not enough for the page to be centered.

If you are getting this issue when saving/restoring the current page, one other solution might be to use a branch that has PR #661. This should restore the zoom and position correctly without using the defaultPage or jumpTo methods.

That being said, this method is public and has more use cases so needs a fix

@kzqsky
Copy link
Author

kzqsky commented Sep 28, 2018

@arthurdick Thank you

@kuerm
Copy link

kuerm commented Dec 19, 2020

@arthurdick Thank you for this solution. Unfortunately it didn't work for me (using com.github.barteksc:android-pdf-viewer:3.2.0-beta.1)
Fortunately this worked:

    override fun jumpTo(page: Int) {
        val currentPage = currentPage
        super.jumpTo(page)

        if (page == 0 && currentPage == 1) {
            val pageOffset = pdfFile.getPageOffset(0, zoom)
            scrollBy(0, 1 * pageOffset.toInt())
        } else if (page == 1) {
            val pageOffset = pdfFile.getPageOffset(0, zoom)
            val factor = if (currentPage > page) 0 else -1
            scrollBy(0, factor * pageOffset.toInt())
        }
    }

@soapgu
Copy link

soapgu commented Jun 26, 2023

this is my solution,it do not need change package source code.(using com.github.barteksc:android-pdf-viewer:3.2.0-beta.1)
@arthurdick Thank you for your solution

  1. create a extention class PDFPlusView
package com.space365.meetingpad.control;

import android.content.Context;
import android.util.AttributeSet;

import com.github.barteksc.pdfviewer.PDFView;
import com.orhanobut.logger.Logger;

import java.lang.reflect.Field;
import java.lang.reflect.Method;

public class PDFPlusView extends PDFView {

    /**
     * Construct the initial view
     *
     * @param context context
     * @param set AttributeSet
     */
    public PDFPlusView(Context context, AttributeSet set) {
        super(context, set);
    }

    public void testForReflect(){
        try {
            Field pdfFileField = PDFView.class.getDeclaredField("pdfFile");
            pdfFileField.setAccessible(true);
            Object pdfFile = pdfFileField.get(this);
            Method getCountMethod = Class.forName("com.github.barteksc.pdfviewer.PdfFile").getDeclaredMethod("getPagesCount");
            getCountMethod.setAccessible(true);
            Object pageCountValue = getCountMethod.invoke( pdfFile );
            if( pageCountValue != null ){
                int pageCount = (int)pageCountValue;
                Logger.i("TestForReflect success,page count %d",pageCount);
            }
        }
        catch (Exception exception){
            Logger.e( "TestForReflect error",exception );
        }

    }


    @Override
    public void jumpTo(int page, boolean withAnimation) {
        try {
            Object pdfFile = this.getReflectField("pdfFile");
            if (pdfFile == null) {
                return;
            }

            Class<?> pdfFileCls = Class.forName("com.github.barteksc.pdfviewer.PdfFile");
            Object pageValue = getReflectMethod(pdfFileCls,"determineValidPageNumberFrom",int.class)
                    .invoke(pdfFile, page);
            if( pageValue != null ){
                page = (int)pageValue;
            }

            float zoom = (float)getReflectField("zoom");
            Object pageOffsetValue = getReflectMethod( pdfFileCls, "getPageOffset",int.class,float.class )
                    .invoke( pdfFile,page,zoom );
            float pageOffset =  pageOffsetValue == null ? 0 : (float)pageOffsetValue;
            float offset = page == 0 ? 0 : -pageOffset;
            boolean swipeVertical = (boolean)getReflectField("swipeVertical");


            Object animationManager = getReflectField("animationManager");
            float currentYOffset = (float)getReflectField("currentYOffset");
            float currentXOffset = (float)getReflectField("currentXOffset");

            Class<?> animationManagerCls = Class.forName("com.github.barteksc.pdfviewer.AnimationManager");
            Method startXAnimationMethod = this.getReflectMethod( animationManagerCls,"startXAnimation",float.class,float.class );
            Method startYAnimationMethod = this.getReflectMethod( animationManagerCls,"startYAnimation",float.class,float.class );
            if (swipeVertical) {
                if (withAnimation) {
                    //animationManager.startYAnimation(currentYOffset, offset);
                    startXAnimationMethod.invoke( animationManager,currentYOffset,offset);
                } else {
                    moveTo(currentXOffset, offset);
                }
            } else {
                Object pageSpacingValue = this.getReflectMethod(pdfFileCls,"getPageSpacing",int.class,float.class)
                        .invoke( pdfFile,page,zoom );
                if( pageSpacingValue != null ){
                    offset += (float)pageSpacingValue / 2f;
                }
                if (withAnimation) {
                    //animationManager.startXAnimation(currentXOffset, offset);
                    startYAnimationMethod.invoke( animationManager, currentXOffset,offset);
                } else {
                    moveTo(offset, currentYOffset);
                }
            }
            this.getReflectMethod(PDFView.class,"showPage",int.class)
                    .invoke( this,page );
        }
        catch (Exception exception){
            Logger.e( "jumpTo error",exception );
        }
    }


    private Object getReflectField(String fieldName) throws IllegalAccessException, NoSuchFieldException {
        Field field = PDFView.class.getDeclaredField(fieldName);
        field.setAccessible(true);
        return field.get(this);
    }

    private Method getReflectMethod( Class<?> targetClass,String method, Class<?>... parameterTypes ) throws NoSuchMethodException {
        Method methodValue = targetClass.getDeclaredMethod(method,parameterTypes);
        methodValue.setAccessible(true);
        return methodValue;
    }
}
  1. declare in xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".fragments.PdfViewerFragment">

    <com.space365.meetingpad.control.PDFPlusView
        android:id="@+id/pdfView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/black"
        tools:layout_editor_absoluteX="-397dp"
        tools:layout_editor_absoluteY="95dp" />

    <Button
        android:id="@+id/btn_test"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="测试反射"
        app:layout_constraintBottom_toBottomOf="@+id/pdfView"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:visibility="gone"/>
</androidx.constraintlayout.widget.ConstraintLayout>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants