Android, прикрепление электронной подписи в PDF с помощью перетаскивания - PullRequest
3 голосов
/ 02 февраля 2020

Я занимаюсь разработкой приложения Android, мне нужно реализовать размещение подписи пользователя (изображения) на перетаскивании PDF пользователем. Я использую средство просмотра PDF (com.github.barteksc.pdfviewer.PDFView), чтобы показать PDF, и я использую слушатель перетаскивания, чтобы получить координаты из вида. но он не помещается в правильное положение на PDF. Я потратил много времени на другие решения, но нет никакой помощи. (или, пожалуйста, предложите любой бесплатный SDK, доступный в Android для достижения того же.)

Пожалуйста, помогите мне решить эту проблему. Вот мой пример кода.

public class MainActivity extends AppCompatActivity implements View.OnTouchListener, View.OnDragListener, OnPageChangeListener, OnPageScrollListener {
private PDFView pdfViewDemo;
private Button buttonGetPage;
private ImageView imageViewDemo;
private ImageView imageDrag;

private String pdfUrl = "/sdcard/sample.pdf";

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_pdf_view);
    findViewById(R.id.rootView).setOnDragListener(this);
    pdfViewDemo = findViewById(R.id.pdfView);
    final File file = new File(pdfUrl);
    pdfViewDemo.setMaxZoom(0);
    pdfViewDemo.fromFile(file)
            .onPageChange(this)
            .onPageScroll(this)
            .spacing(10)
            .swipeHorizontal(true)
            .enableDoubletap(false)
            .load();

    //Implementation of Drag and Drop---------------------------------------------
    imageDrag = findViewById(R.id.imageDrag);
    imageDrag.setOnTouchListener(this);
    //Implementation of Drag and Drop---------------------------------------------

    imageViewDemo = findViewById(R.id.imageDemo);

    buttonGetPage = findViewById(R.id.buttonGetPage);
    buttonGetPage.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            ArrayList<Bitmap> bitmaps = pdfToBitmap(file);
            pdfViewDemo.setVisibility(View.GONE);
            imageViewDemo.setVisibility(View.VISIBLE);
            imageViewDemo.setImageBitmap(bitmaps.get(0));
            Log.e("test", "Bitmaps: " + bitmaps.size());
        }
    });


}

private ArrayList<Bitmap> pdfToBitmap(File pdfFile) {
    ArrayList<Bitmap> bitmaps = new ArrayList<>();

    try {
        PdfRenderer renderer = new PdfRenderer(ParcelFileDescriptor.open(pdfFile, ParcelFileDescriptor.MODE_READ_ONLY));

        Bitmap bitmap;
        final int pageCount = renderer.getPageCount();
        for (int i = 0; i < pageCount; i++) {
            PdfRenderer.Page page = renderer.openPage(i);

            int width = getResources().getDisplayMetrics().densityDpi / 72 * page.getWidth();
            int height = getResources().getDisplayMetrics().densityDpi / 72 * page.getHeight();
            bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);

            page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);

            bitmaps.add(bitmap);

            // close the page
            page.close();

        }

        // close the renderer
        renderer.close();
    } catch (Exception ex) {
        ex.printStackTrace();
    }

    return bitmaps;

}

@Override
public void onPageChanged(int page, int pageCount) {
    Log.e("test", "onPageChanged() called with: page = [" + page + "], pageCount = [" + pageCount + "]");
}

@Override
public void onPointerCaptureChanged(boolean hasCapture) {
    Log.e("test", "onPointerCaptureChanged() called with: hasCapture = [" + hasCapture + "]");
}

@Override
public void onPageScrolled(int page, float positionOffset) {
    Log.e("test", "onPageScrolled() called with: page = [" + page + "], positionOffset = [" + positionOffset + "]");
}

@Override
public boolean onTouch(View view, MotionEvent event) {
    Log.e("test", "onTouch() called with: v = [" + view + "], event = [" + event + "]");
    if (event.getAction() == MotionEvent.ACTION_DOWN) {
        View.DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
        view.startDrag(null, shadowBuilder, view, 0);
        return true;
    } else {
        return false;
    }
}

@Override
public boolean onDrag(View v, DragEvent event) {
    int action = event.getAction();
    switch (action) {
        case DragEvent.ACTION_DRAG_STARTED:
            Log.e("test", "onDrag: ACTION_DRAG_STARTED");
            break;
        case DragEvent.ACTION_DRAG_ENTERED:
            Log.e("test", "onDrag: ACTION_DRAG_ENTERED");
            break;
        case DragEvent.ACTION_DRAG_EXITED:
            Log.e("test", "onDrag: ACTION_DRAG_EXITED");
            break;
        case DragEvent.ACTION_DROP:
            Log.e("test", "onDrag: ACTION_DROP");
            Log.e("test-", "X: " + (int) event.getX());
            Log.e("test-", "Y: " + (int) event.getY());
            getPdfCoordinates((int) event.getX(), (int) event.getY());
            /*View tvState = (View) event.getLocalState();
            val tvParent = tvState.parent as ViewGroup
            tvParent.removeView(tvState)
            val container = view as LinearLayout
            container.addView(tvState)
            tvParent.removeView(tvState)
            tvState.x = dragEvent.x
            tvState.y = dragEvent.y
            view.addView(tvState)
            view.setVisibility(View.VISIBLE)
            int x = (int) v.getX();
            int y = (int) v.getY();
            RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(x, y);
            textTitle.setLayoutParams(layoutParams);*/
            break;
        case DragEvent.ACTION_DRAG_ENDED:
            Log.e("test", "onDrag: ACTION_DRAG_ENDED" + v.getX() + ":" + v.getY());
            imageDrag.setVisibility(View.VISIBLE);
            break;
        default:
            break;
    }
    return true;
}

private void getPdfCoordinates(int x, int y) {
    Log.e("test-", "PDF: getMeasuredWidth: " + pdfViewDemo.getMeasuredWidth());
    Log.e("test-", "PDF: getWidth: " + pdfViewDemo.getWidth());
    Log.e("test-", "PDF: getOptimalPageHeight: " + pdfViewDemo.getOptimalPageHeight());
    Log.e("test-", "PDF: getOptimalPageWidth: " + pdfViewDemo.getOptimalPageWidth());
    Log.e("test-", "PDF: getMeasuredWidthAndState: " + pdfViewDemo.getMeasuredWidthAndState());

    Log.e("test-", "PDF: getMinimumHeight: " + pdfViewDemo.getMinimumHeight());
    Log.e("test-", "PDF: getMinimumWidth: " + pdfViewDemo.getMinimumWidth());

    x= (int) pdfViewDemo.getOptimalPageHeight()/2-x;
    y=(int)pdfViewDemo.getOptimalPageWidth()/2-y;
    addImageToPdf(x, y);
}

private void addImageToPdf(int x, int y) {
    Log.e("test", "addImageToPdf() called with: x = [" + x + "], y = [" + y + "]" + pdfViewDemo.getCurrentPage());
    try {
        PdfReader reader = new PdfReader(pdfUrl);
        PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("/sdcard/test_pdf.pdf"));
        PdfContentByte content = stamper.getOverContent(pdfViewDemo.getCurrentPage()+1);

        com.itextpdf.text.Image image = Image.getInstance("/sdcard/sign_1.jpg");


        image.scaleAbsoluteHeight(50);
        image.scaleAbsoluteWidth((image.getWidth() * 50) / image.getHeight());

        image.setAbsolutePosition(y, x);

        content.addImage(image);

        stamper.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
}

Вот скриншоты ввода и вывода enter image description here enter image description here

1 Ответ

0 голосов
/ 11 февраля 2020

Согласно этому ответу , координаты данной страницы могут быть любыми и должны быть проверены с помощью PdfReader.

Может также быть несколько других факторов, влияющих на позиционирование.

  • Система координат PDF может масштабироваться иначе, чем андроиды.
  • PdfStamper может поставить штамп неожиданным способом (я не смог найти достаточную документацию), поэтому требуется некоторое тестирование, чтобы выяснить, где Точно штамп ставится для данных координат.
  • Координаты события касания, которое вы перехватываете при отбрасывании, являются абсолютными, но должны быть относительно положения PdfView. Это может быть достигнуто путем получения абсолютной позиции PdfView и вычитания ее из координат TouchEvent.

Несколько советов, которые помогут с отладкой.

...