原文地址: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阅读器就完成了,哈哈,想进一步增加功能的话就优化修改并扩展一下吧!