一,简介
pdf文件在android sdk-21 开始就出现了PdfRender,Android Sdk-27就可以实现渲染了。
二,工作原理
获取文件标识符 --- 初始化定义PdfRender --- 获取当前页--- 生成bitmap -- ImgView展现
三,这里我使用的工具
ViewPager+PhotoView + Fragment
PhotoView --- 使得图片可放大,缩小
ViewPager --- 使得Fragment可以滑动
Fragment --- 使得生成的bitmap图再Fragment上更换呈现
四,布局
主布局:activity_view_pager.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000">
<TextView
android:id="@+id/tv_indicator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:textSize="30sp"
android:textColor="#ffffff"
/>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/tv_indicator"
/>
</RelativeLayout>
次布局:fragment_picture_slide.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/iv_main_pic"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@android:color/white"
android:scaleType="fitCenter"
android:contentDescription="@null"/>
</LinearLayout>
实现函数
public class ViewPagerActivity extends AppCompatActivity {
//渲染pdf
private static PdfRenderer mPdfRenderer;
/**
* pdf文件(此文件放在asset文件夹内)
*/
private static final String FILENAME = "sample.pdf";
/**
* pdf文件描述符
*/
private static ParcelFileDescriptor mFileDescriptor;
/**
* 屏幕上当前显示的页面
*/
private static PdfRenderer.Page mCurrentPage;
/**
* 总页数
*/
private int countnum;
private ViewPager viewPager;
private TextView tv_indicator;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_view_pager);
try {
openRenderer(this);
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(this, "Error! " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
countnum = mPdfRenderer.getPageCount();
viewPager = (ViewPager) findViewById(R.id.viewpager);
tv_indicator = (TextView) findViewById(R.id.tv_indicator);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
tv_indicator.setText(String.valueOf(position+1)+"/"+countnum);//<span style="white-space: pre;">在当前页面滑动至其他页面后,获取position值</span>
}
@Override
public void onPageSelected(int position) {
}
@Override
public void onPageScrollStateChanged(int state) {
}
});
viewPager.setAdapter(new PictureSlidePagerAdapter(getSupportFragmentManager()));
}
/**
* 适配器
*/
private class PictureSlidePagerAdapter extends FragmentStatePagerAdapter {
public PictureSlidePagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
return MyFragment.newInstance(position);//返回展示不同bitmap图片的MyFragment
}
@Override
public int getCount() {
return countnum;//指定ViewPager的总页数
}
}
public static class MyFragment extends Fragment{
private int index ;
private Bitmap bitmap;
private PhotoViewAttacher mAttacher;
private ImageView imageView;
public static MyFragment newInstance(int index ) {
//防止图片混乱,使用Bundle传值给Oncreate
MyFragment f = new MyFragment();
Bundle args = new Bundle();
args.putInt("index", index);
f.setArguments(args);
return f; //获得一个包含图片位置的MyFragment的实例
}
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
index = getArguments() != null ? getArguments().getInt("index") : 0;
bitmap = showPage(index);
}
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v=inflater.inflate(R.layout.fragment_picture_slide,container,false);
imageView= (ImageView) v.findViewById(R.id.iv_main_pic);
mAttacher = new PhotoViewAttacher(imageView);//使用PhotoViewAttacher为图片添加支持缩放、平移的属性
imageView.setImageBitmap(bitmap);
mAttacher.update();//调用PhotoViewAttacher的update()方法,使图片重新适配布局
return v;
}
}
/**
* 打开源文件
*/
private void openRenderer(Context context) throws IOException {
// 在目录中读取PDF。
File file = new File(context.getCacheDir(), FILENAME);
if (!file.exists()) {
InputStream asset = context.getAssets().open(FILENAME);
FileOutputStream output = new FileOutputStream(file);
final byte[] buffer = new byte[1024];
int size;
while ((size = asset.read(buffer)) != -1) {
output.write(buffer, 0, size);
}
asset.close();
output.close();
}
mFileDescriptor = ParcelFileDescriptor.open(file, ParcelFileDescriptor.MODE_READ_ONLY);
// 这是我们用来渲染PDF的PdfRenderer。
if (mFileDescriptor != null) {
mPdfRenderer = new PdfRenderer(mFileDescriptor);
}
}
/**
* 显示指定的PDF页面到屏幕。
*
* @param index The page index.
*/
private static Bitmap showPage(int index) {
if (mPdfRenderer.getPageCount() <= index) {
return null;
}
// 在打开另一个页面之前,请确保关闭当前页面。
if (null != mCurrentPage) {
mCurrentPage.close();
}
//使用“OpenPage”打开PDF中的特定页面。
mCurrentPage = mPdfRenderer.openPage(index);
// Important: the destination bitmap must be ARGB (not RGB).
Bitmap bitmap = Bitmap.createBitmap(mCurrentPage.getWidth(), mCurrentPage.getHeight(),
Bitmap.Config.ARGB_8888);
// 这里,我们将页面渲染到位图上。
// 要渲染页面的一部分,使用第二个和第三个参数。传递空值以获得默认结果。
// Pass either RENDER_MODE_FOR_DISPLAY or RENDER_MODE_FOR_PRINT for the last parameter.
mCurrentPage.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY);
// 我们准备向用户显示bitmap
return bitmap;
}
@Override
protected void onStop() {
try {
closeRenderer();
} catch (IOException e) {
e.printStackTrace();
}
super.onStop();
}
/**
* 关闭相关的资源。
*
* @throws java.io.IOException When the PDF file cannot be closed.
*/
private void closeRenderer() throws IOException {
if (null != mCurrentPage) {
mCurrentPage.close();
}
mPdfRenderer.close();
mFileDescriptor.close();
}
}
注意:导入PhotoView包
allprojects {
repositories {
maven { url "https://jitpack.io" }
}
}
dependencies {
implementation 'com.github.chrisbanes:PhotoView:2.0.0'
}