新版超简单的PDF阅读器

    xiaoxiao2025-11-27  4

    原文地址:http://blog.csdn.net/BingHongChaZuoAn/article/details/52213611

    本PDF阅读器的开发是基于android23版本的,其他版本暂时没有做适配(因为google旧版没提供API,需要借助阿帕奇或者其他的API),本篇代码不超过320行,不错吧。支持pdf的页数,下一页,上一页,跳转到某一页。然后就是pdf页面的缩放和平移。

    别的不多说了,直接贴代码吧(代码不够精简,需要优化下,不过功能可以):

    public class PdfActivity extends Activity implements View.OnClickListener, View.OnTouchListener { private TextView totalPageTV; private EditText targetPageET; private TextView startToScanTV; private TextView nextPageTV; private TextView prePageTV; private ImageView pdfImg; private int currentPage = 0; private int totalPage = 0; private PdfRenderer renderer; private ParcelFileDescriptor parcelFileDescriptor; private String filePath = "123.pdf"; private int fileType = ASSETS_FILE; public static final String FILE_PATH_KEY = "file_path"; public static final String FILE_TYPE_KEY = "file_type"; public static final int ASSETS_FILE = 0;//assets文件 public static final int CUSTOM_FILE = 1;//普通文件 private float scale = 1.0f; private Matrix matrix = new Matrix(); private Matrix savedMatrix = new Matrix(); private static final int NONE = 0; private static final int DRAG = 1; private static final int ZOOM = 2; private int mode = NONE; // 第一个按下的手指的点 private PointF startPoint = new PointF(); // 两个按下的手指的触摸点的中点 private PointF midPoint = new PointF(); // 初始的两个手指按下的触摸点的距离 private float oriDis = 1f; /** * 最大屏幕触点数量 */ private final int MAX_TOUCH_POINT = 3; private Bitmap bitmap; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle bundle = getIntent().getExtras(); if (bundle != null) { filePath = bundle.getString(FILE_PATH_KEY, "abc.pdf"); fileType = bundle.getInt(FILE_TYPE_KEY, ASSETS_FILE); } setContentView(R.layout.pdf_layout); initViews(); ititPDF(); } private void ititPDF() { try { File file = null; if (fileType == CUSTOM_FILE) { file = new File(filePath); } else if (fileType == ASSETS_FILE) { file = FileUtil.fileFromAsset(this, filePath); } parcelFileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY); renderer = new PdfRenderer(parcelFileDescriptor); totalPage = renderer.getPageCount() - 1; totalPageTV.setText(String.valueOf(totalPage + 1)); showPdf(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } private void initViews() { totalPageTV = (TextView) findViewById(R.id.total_num_tv); targetPageET = (EditText) findViewById(R.id.target_page_tv); startToScanTV = (TextView) findViewById(R.id.start_to_scan_tv); nextPageTV = (TextView) findViewById(R.id.next_page_tv); prePageTV = (TextView) findViewById(R.id.pre_page_tv); pdfImg = (ImageView) findViewById(R.id.pdf_img); startToScanTV.setOnClickListener(this); nextPageTV.setOnClickListener(this); prePageTV.setOnClickListener(this); pdfImg.setOnTouchListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.start_to_scan_tv: toTargetPage(); break; case R.id.pre_page_tv: lastPage(); break; case R.id.next_page_tv: nextPage(); break; } } private void toTargetPage() { String target = targetPageET.getText().toString(); int targetPage = Integer.valueOf(target); if (targetPage <= 0 || targetPage > totalPage) { Toast.makeText(PdfActivity.this, "您选的页面超出了范围,请重新选择吧!", Toast.LENGTH_SHORT).show(); } else { currentPage = targetPage; showPdf(); } } private void nextPage() { if (currentPage >= totalPage) { Toast.makeText(PdfActivity.this, "没有下一页了哦!", Toast.LENGTH_SHORT).show(); } else { currentPage++; showPdf(); } } private void lastPage() { if (currentPage <= 0) { Toast.makeText(PdfActivity.this, "上一页不存在啊!", Toast.LENGTH_SHORT).show(); } else { currentPage--; showPdf(); } } private void showPdf() { targetPageET.setText(String.valueOf(currentPage)); PdfRenderer.Page page = renderer.openPage(currentPage); int height = page.getHeight(); int width = page.getWidth(); Matrix matrix = new Matrix(); int windowWidth = getResources().getDisplayMetrics().widthPixels; int windowheight = getResources().getDisplayMetrics().heightPixels; float scaleX = (float) ((scale * windowWidth) / width); float scaleY = (float) ((scale * windowheight) / height); matrix.setScale(scaleX, scaleY); if (bitmap != null) { bitmap.recycle(); } bitmap = Bitmap.createBitmap(windowWidth, windowheight, Bitmap.Config.ARGB_4444); Rect rect = new Rect(0, 0, windowWidth, windowheight); page.render(bitmap, rect, matrix, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY); pdfImg.setImageBitmap(bitmap); if (page != null) { page.close(); } } @Override protected void onDestroy() { super.onDestroy(); if (bitmap != null) { bitmap.recycle(); } if (renderer != null) { renderer.close(); } if (parcelFileDescriptor != null) { try { parcelFileDescriptor.close(); } catch (IOException e) { e.printStackTrace(); } } } @Override public boolean onTouch(View v, MotionEvent event) { ImageView view = (ImageView) v; // 进行与操作是为了判断多点触摸 switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: // 第一个手指按下事件 matrix.set(view.getImageMatrix()); savedMatrix.set(matrix); startPoint.set(event.getX(), event.getY()); mode = DRAG; break; case MotionEvent.ACTION_POINTER_DOWN: // 第二个手指按下事件 oriDis = distance(event); if (oriDis > 10f) { savedMatrix.set(matrix); midPoint = middle(event); mode = ZOOM; } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: // 手指放开事件 mode = NONE; break; case MotionEvent.ACTION_MOVE: // 手指滑动事件 if (mode == DRAG) { // 是一个手指拖动 matrix.set(savedMatrix); matrix.postTranslate(event.getX() - startPoint.x, event.getY() - startPoint.y); } else if (mode == ZOOM) { // 两个手指滑动 float newDist = distance(event); if (newDist > 10f) { matrix.set(savedMatrix); float scale = newDist / oriDis; matrix.postScale(scale, scale, midPoint.x, midPoint.y); } } break; } // 设置ImageView的Matrix view.setImageMatrix(matrix); return true; } // 计算两个触摸点之间的距离 private float distance(MotionEvent event) { float x = event.getX(0) - event.getX(1); float y = event.getY(0) - event.getY(1); return (float) Math.sqrt(x * x + y * y); } // 计算两个触摸点的中点 private PointF middle(MotionEvent event) { float x = event.getX(0) + event.getX(1); float y = event.getY(0) + event.getY(1); return new PointF(x / 2, y / 2); } }

    FileUtil里面就这两个方法,其他的就不贴了,太长,也和本文没啥关系

    public static File fileFromAsset(Context context, String assetName) throws IOException { File outFile = new File(context.getCacheDir(), assetName); copy(context.getAssets().open(assetName), outFile); return outFile; } public static void copy(InputStream inputStream, File output) throws IOException { FileOutputStream outputStream = null; try { outputStream = new FileOutputStream(output); boolean read = false; byte[] bytes = new byte[1024]; int read1; while ((read1 = inputStream.read(bytes)) != -1) { outputStream.write(bytes, 0, read1); } } finally { try { if (inputStream != null) { inputStream.close(); } } finally { if (outputStream != null) { outputStream.close(); } } } }

    xml文件:

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <ImageView android:id="@+id/pdf_img" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="matrix" android:layout_weight="1" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="17dp" android:padding="5dp" android:text="共" android:textSize="12sp" /> <TextView android:id="@+id/total_num_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:text="12" android:textSize="12sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:text="页" android:textSize="12sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:padding="5dp" android:text="第" android:textSize="12sp" /> <EditText android:id="@+id/target_page_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:inputType="number" android:padding="5dp" android:text="0" android:textSize="12sp" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:text="页" android:textSize="12sp" /> <TextView android:id="@+id/start_to_scan_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="5dp" android:text="GO" android:textSize="12sp" /> <TextView android:id="@+id/pre_page_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:padding="5dp" android:text="上一页" android:textSize="12sp" /> <TextView android:id="@+id/next_page_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="20dp" android:padding="5dp" android:text="下一页" android:textSize="12sp" /> </LinearLayout> </LinearLayout>

    o了,就这么多,一个简单的pdf阅读器就完成了,哈哈,想进一步增加功能的话就优化修改并扩展一下吧!

    转载请注明原文地址: https://ju.6miu.com/read-1304462.html
    最新回复(0)