I have a custom listview and I want to make pdf from the whole listview. I refered many posts and implemented below code which converts my listview to pdf. But problem is its not containing the whole listview item. Only first few items are available in the pdf.
My function to convert listview to pdf is
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String state = Environment.getExternalStorageState();
if (!Environment.MEDIA_MOUNTED.equals(state)) {
}
File pdfDir = new File(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_DOCUMENTS), "MyProject");
if (!pdfDir.exists()){
pdfDir.mkdir();
}
Bitmap screen = getWholeListViewItemsToBitmap();
File pdfFile = new File(pdfDir, "myPdfFile_new.pdf");
try {
Document document = new Document();
PdfWriter.getInstance(document, new FileOutputStream(pdfFile));
document.open();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
screen.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
addImage(document,byteArray);
document.close();
}
catch (Exception e){
e.printStackTrace();
}
}
});
addImage method
private static void addImage(Document document,byte[] byteArray)
{
Image image = null;
try
{
image = Image.getInstance(byteArray);
}
catch (BadElementException e)
{
e.printStackTrace();
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
catch (IOException e)
{
e.printStackTrace();
}
try
{
document.add(image);
} catch (DocumentException e) {
e.printStackTrace();
}
}
method to get list items
public Bitmap getWholeListViewItemsToBitmap() {
ListView listview = StockReportActivity.category_list;
ListAdapter adapter = listview.getAdapter();
int itemscount = adapter.getCount();
int allitemsheight = 0;
List<Bitmap> bmps = new ArrayList<Bitmap>();
for (int i = 0; i < itemscount; i++) {
View childView = adapter.getView(i, null, listview);
childView.measure(View.MeasureSpec.makeMeasureSpec(listview.getWidth(), View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
childView.layout(0, 0, childView.getMeasuredWidth(), childView.getMeasuredHeight());
childView.setDrawingCacheEnabled(true);
childView.buildDrawingCache();
bmps.add(childView.getDrawingCache());
allitemsheight+=childView.getMeasuredHeight();
}
Bitmap bigbitmap = Bitmap.createBitmap(listview.getMeasuredWidth(), allitemsheight, Bitmap.Config.ARGB_8888);
Canvas bigcanvas = new Canvas(bigbitmap);
Paint paint = new Paint();
int iHeight = 0;
for (int i = 0; i < bmps.size(); i++) {
Bitmap bmp = bmps.get(i);
bigcanvas.drawBitmap(bmp, 0, iHeight, paint);
iHeight+=bmp.getHeight();
bmp.recycle();
bmp=null;
}
return bigbitmap;
}
My listview contains large number of items in it, so how can i convert the whole listview to pdf. All your suggestions are appreciated
You can get the number of items displayed on screen in recyclerView, so create bitmap for first set of views, after that you can dynamically scroll to item below the last item displayed (i.e noOfItemDisplayed+1), again get bitmap, likewise all get all bitmaps into ArrayList<Bitmap> from which you can create pdf file, refer to code below to create pdf from arraylist of bitmaps:
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
private void createPdf() throws IOException {
PdfDocument document = new PdfDocument();
PdfDocument.Page page = null;
// crate a page description
for (int i = 0; i < bitmaps.size(); i++) {
Bitmap bitmap = bitmaps.get(i);
PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(1400, 1979, i).create();
// start a page
page = document.startPage(pageInfo);
if (page == null) {
return;
}
Canvas canvas = page.getCanvas();
canvas.drawBitmap(bitmap, 0, 0, null);
document.finishPage(page);
}
// finish the page
// write the document content
fileHandler = new FileHandler(this, getString(R.string.app_name));
File pdf = fileHandler.getNewFileToWrite(AppConstants.FileExtensions.PDF); //crete and get file
try {
document.writeTo(new FileOutputStream(pdf));
} catch (IOException e) {
logger.error(e);
}
// close the document
document.close();
}
Now you can create a Bitmap for all childviews in the ListView.
After that, please process Bitmap as you like.
public List<Bitmap> getWholeListViewItemsToBitmap(ListView lv, Adapter adapter) {
List<Bitmap> listBitmap = new ArrayList<Bitmap>();
int itemsCount = adapter.getCount();
int lvViewLines = lv.getChildCount();
for(int from = 0; from < itemsCount; from+= lvViewLines) {
int to = from + lvViewLines;
for(int i = from; i < to && i < itemsCount; i++) {
View childView = adapter.getView(i, null, lv);
childView.measure(View.MeasureSpec.makeMeasureSpec(lv.getWidth(), View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
childView.layout(0, 0, childView.getMeasuredWidth(), childView.getMeasuredHeight());
childView.setDrawingCacheEnabled(true);
childView.buildDrawingCache();
listBitmap.add(childView.getDrawingCache());
}
lv.setScrollY(lvViewLines);
}
return listBitmap;
}
Related
I was using RecyclerView to create PDF previously. I want to add share and print functionality for which I want to create PDF with content in it. The method I was using was
public static void generatePDF(RecyclerView view, boolean isShareTrue, Context context, boolean isWeekly) {
RecyclerView.Adapter adapter = view.getAdapter();
Bitmap bigBitmap = null;
if (adapter != null) {
int size = adapter.getItemCount();
int height = 0;
Paint paint = new Paint();
int iHeight = 0;
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
// Use 1/8th of the available memory for this memory cache.
final int cacheSize = maxMemory / 8;
LruCache<String, Bitmap> bitmaCache = new LruCache<>(cacheSize);
for (int i = 0; i < size; i++) {
RecyclerView.ViewHolder holder = adapter.createViewHolder(view, adapter.getItemViewType(i));
adapter.onBindViewHolder(holder, i);
holder.itemView.measure(View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
holder.itemView.layout(0, 0, holder.itemView.getMeasuredWidth(), holder.itemView.getMeasuredHeight());
holder.itemView.setDrawingCacheEnabled(true);
holder.itemView.buildDrawingCache();
Bitmap drawingCache = holder.itemView.getDrawingCache();
if (drawingCache != null) {
bitmaCache.put(String.valueOf(i), drawingCache);
}
height += holder.itemView.getMeasuredHeight();
}
bigBitmap = Bitmap.createBitmap(view.getMeasuredWidth(), height, Bitmap.Config.ARGB_8888);
Canvas bigCanvas = new Canvas(bigBitmap);
bigCanvas.drawColor(Color.WHITE);
Document document = new Document(PageSize.A4);
File file;
if (isWeekly)
file = new File(Environment.getExternalStorageDirectory(), "Weekly_list_" + AppPreferences.INSTANCE.getUserId() + ".pdf");
else
file = new File(Environment.getExternalStorageDirectory(), "Open_Cycle_List_" + AppPreferences.INSTANCE.getUserId() + ".pdf");
try {
PdfWriter.getInstance(document, new FileOutputStream(file));
} catch (DocumentException | FileNotFoundException e) {
e.printStackTrace();
}
for (int i = 0; i < size; i++) {
try {
//Adding the content to the document
Bitmap bmp = bitmaCache.get(String.valueOf(i));
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
Image image = Image.getInstance(stream.toByteArray());
float scaler = ((document.getPageSize().getWidth() - document.leftMargin()
- document.rightMargin() - 0) / image.getWidth()) * 100; // 0 means you have no indentation. If you have any, change it.
image.scalePercent(scaler);
image.setAlignment(com.itextpdf.text.Image.ALIGN_CENTER | com.itextpdf.text.Image.ALIGN_TOP);
if (!document.isOpen()) {
document.open();
}
document.add(image);
} catch (Exception ex) {
Log.e("TAG-ORDER PRINT ERROR", ex.getMessage());
}
}
if (document.isOpen()) {
document.close();
}
if (isShareTrue) {
Intent intentShareFile = new Intent(Intent.ACTION_SEND);
if (file.exists()) {
Uri pdfUri;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
pdfUri = FileProvider.getUriForFile(context, context.getPackageName() + ".provider", file);
} else {
pdfUri = Uri.fromFile(file);
}
intentShareFile.setType("application/pdf");
intentShareFile.putExtra(Intent.EXTRA_STREAM, pdfUri);
intentShareFile.putExtra(Intent.EXTRA_SUBJECT, "Sharing File...");
intentShareFile.putExtra(Intent.EXTRA_TEXT, "Sharing File...");
context.startActivity(Intent.createChooser(intentShareFile, "Share File"));
}
} else {
Toast.makeText(context, "PDF Generated successfully", Toast.LENGTH_LONG).show();
}
}
}
Now I have replaced recycler view with ExpandableListView and my print and share functionality is not working.
I want to create PDF with ExpandableListView content.
I want to create multiple page pdf from Android listview. I have successfully achieved converting all the listview items into pdf even if they are not all visible using itextg. The problem I faced is that if the items in the listview or the captured image of the listview exceeds the length of the page in the pdf it cuts the the rest of the items.
I want to create a multiple page pdf if the first page is full then write the rest of the image part in the second image.
This is the code which creates the pdf by capturing all the listview item:
//method which generate pdf of the attendance data
private void save_as_pdf() {
//First Check if the external storage is writable
String state = Environment.getExternalStorageState();
if (!Environment.MEDIA_MOUNTED.equals(state)) {
// Toast.makeText(context,"")
}
//Create a directory for your PDF
final File pdfDir = new File(Environment.getExternalStorageDirectory() + "/Documents", "attendance_report");
if (!pdfDir.exists()) {
pdfDir.mkdir();
}
//take screen shoot of the entire listview of the attendance report
ListView listview = studentlist;
ListAdapter adapter = listview.getAdapter();
int itemscount = adapter.getCount();
int allitemsheight = 0;
List<Bitmap> bmps = new ArrayList<Bitmap>();
for (int i = 0; i < itemscount; i++) {
View childView = adapter.getView(i, null, listview);
childView.measure(
View.MeasureSpec.makeMeasureSpec(listview.getWidth(), View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
childView.layout(0, 0, childView.getMeasuredWidth(), childView.getMeasuredHeight());
childView.setDrawingCacheEnabled(true);
childView.buildDrawingCache();
bmps.add(childView.getDrawingCache());
allitemsheight += childView.getMeasuredHeight();
}
Bitmap bigbitmap = Bitmap.createBitmap(listview.getMeasuredWidth(), allitemsheight,
Bitmap.Config.ARGB_8888);
Canvas bigcanvas = new Canvas(bigbitmap);
bigcanvas.drawColor(getResources().getColor(R.color.white));
Paint paint = new Paint();
int iHeight = 0;
for (int i = 0; i < bmps.size(); i++) {
Bitmap bmp = bmps.get(i);
bigcanvas.drawBitmap(bmp, 0, iHeight, paint);
iHeight += bmp.getHeight();
bmp.recycle();
bmp = null;
}
//Now create the name of your PDF file that you will generate
File pdfFile = new File(pdfDir, "report_for( " + course + "," + semister + section + "," + date + ").pdf");
try {
com.itextpdf.text.Document document = new com.itextpdf.text.Document();
PdfWriter.getInstance(document, new FileOutputStream(pdfFile));
document.addTitle("Attendance Report Generated For course:" + course + " Semester:" + semister + " Section:" + section + " Date:" + date);
document.addHeader("Header", "Department Of Information Science");
document.addCreator("Department Of Information Science");
document.addCreationDate();
document.bottomMargin();
document.setPageCount(3);
document.open();
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bigbitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
addImage(document, byteArray);
document.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private void addImage(com.itextpdf.text.Document document, byte[] byteArray) {
Image image = null;
try {
image = Image.getInstance(byteArray);
} catch (BadElementException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// image.scaleAbsolute(150f, 150f);
try {
document.add(image);
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//take screen shot all records from listview
for (int i = 0; i < itemscount; i++) {
listview.setSelection(i);
View childView = adapter.getView(i, null, listview);
ViewGroup.LayoutParams lp = childView.getLayoutParams();
if (lp == null) {
lp = new ViewGroup.LayoutParams(-2,-2);
}
lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;
lp.width = ViewGroup.LayoutParams.WRAP_CONTENT;
childView.setLayoutParams(lp);
childView.measure(View.MeasureSpec.makeMeasureSpec(listview.getWidth(),
View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
childView.layout(0, 0, childView.getMeasuredWidth(),
childView.getMeasuredHeight());
childView.setDrawingCacheEnabled(true);
childView.buildDrawingCache();
bmps.add(childView.getDrawingCache());
allitemsheight += childView.getMeasuredHeight();
}
I try to save a screenshot of the whole ListView as png in the internal memory and send it to other apps. But if I do it again, the screenshot is not up to date. It's the same screenshot, but I changed the data before sending it.
I use the following code for creating the screenshot:
public static Bitmap getWholeListViewItemsToBitmap(SearchableAdapter adapter, ListView listview ) {
int itemscount = adapter.getCount();
int allitemsheight = 0;
List<Bitmap> bmps = new ArrayList<>();
for (int i = 0; i < itemscount; i++) {
View childView = adapter.getView(i, null, listview);
childView.measure(View.MeasureSpec.makeMeasureSpec(listview.getWidth(), View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
childView.layout(0, 0, childView.getMeasuredWidth(), childView.getMeasuredHeight());
childView.setDrawingCacheEnabled(true);
childView.destroyDrawingCache();
childView.buildDrawingCache();
bmps.add(childView.getDrawingCache());
allitemsheight+=childView.getMeasuredHeight();
}
Bitmap bigbitmap = Bitmap.createBitmap(listview.getMeasuredWidth(), allitemsheight, Bitmap.Config.ARGB_8888);
Canvas bigcanvas = new Canvas(bigbitmap);
Paint paint = new Paint();
int iHeight = 0;
for (int i = 0; i < bmps.size(); i++) {
Bitmap bmp = bmps.get(i);
bigcanvas.drawBitmap(bmp, 0, iHeight, paint);
iHeight+=bmp.getHeight();
bmp.recycle();
bmp=null;
}
return bigbitmap;
}
This Code saves the screenshot:
public static boolean storeScreenshot(Context context, Bitmap screenshot) {
try {
File imagePath = new File(context.getCacheDir(), "images");
if (!imagePath.exists())
imagePath.mkdirs();
File newFile = new File(imagePath, "image.png");
if (newFile.exists()){
newFile.delete();
newFile = new File(imagePath, "image.png");
}
FileOutputStream stream = new FileOutputStream(newFile.getAbsolutePath()); // overwrites this image every time
screenshot.compress(Bitmap.CompressFormat.PNG, 100, stream);
stream.close();
return true;
} catch (IOException e) {
e.printStackTrace();
return false;
}
}
This Code opens the screenshot and use the shareintent to send it:
try {
Helper.storeScreenshot(getApplicationContext(), Helper.getWholeListViewItemsToBitmap(adapter, listview));
File imagePath = new File(getApplicationContext().getCacheDir(), "images");
File screenshot = new File(imagePath, "image.png");
Uri contentUri = null;
if (screenshot.exists())
contentUri = FileProvider.getUriForFile(getApplicationContext(), "com.myApp.fileprovider", screenshot);
if (contentUri != null) {
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
shareIntent.setDataAndType(contentUri, getContentResolver().getType(contentUri));
shareIntent.putExtra(Intent.EXTRA_STREAM, contentUri);
startActivity(Intent.createChooser(shareIntent, "App auswählen"));
}
}
catch(Exception e){
Toast.makeText(getApplicationContext(),"Fehler beim Erstellen des Screenshots!", Toast.LENGTH_LONG);
}
If i try to share the Listview again with changed data, it allways sends some old screenshot.
Anybody an idea?
Thanks a lot
The Solution is
"The cache isn't updated if the filename remains same. I solved this
by deleting the contents of the directory and setting the filename to
the current date in milliseconds. – Gurupad Mamadapur Apr 12 at 17:00"
So I changed the code of the save method to:
public static String storeScreenshot(Context context, Bitmap screenshot) {
try {
File imagePath = new File(context.getCacheDir(), "images");
if (!imagePath.exists())
imagePath.mkdirs();
File[] imagePathDir = imagePath.listFiles();
if(imagePathDir != null){
for (File file : imagePathDir ){
file.delete();
}
}
File screenshotFile = new File(imagePath, System.currentTimeMillis()+".png");
FileOutputStream stream = new FileOutputStream(screenshotFile.getAbsolutePath());
screenshot.compress(Bitmap.CompressFormat.PNG, 100, stream);
stream.close();
return screenshotFile.getName();
} catch (IOException e) {
e.printStackTrace();
return "";
}
It's return the filename, now it works.
Question is already asked here : create PDF of RecyclerView in FULL length
And I also have same Question as i haven't found solution yet, I want to Generate PDF of RecyclerView Content with full length. but did't found solution.
I have already tried all the available solutions and all the possible ways to generate PDF from RecycleView.
Solutions which i have already tried :
https://gist.github.com/PrashamTrivedi/809d2541776c8c141d9a
Take a screenshot of RecyclerView in FULL length
Convert Listview Items into a single Bitmap Image
Have tried all solutions which mentioned above but any of them not working with me and getting error, sometime width & height issue or sometime getting empty white bitmap as output don't know why.
Problem :
I have RecyclerView with HTML Content as well as Images in between contents.
Consider Following Screen as RecyclerView with content.
having content in RecyclerView same as above image with 100+ items.
RecyclerView Item Layout :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:fresco="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<com.facebook.drawee.view.SimpleDraweeView
android:id="#+id/leftImage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:adjustViewBounds="true"
android:maxHeight="350dp"
fresco:actualImageScaleType="fitCenter"
fresco:placeholderImage="#color/white" />
<jp.wasabeef.richeditor.RichEditor
android:id="#+id/editor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/margin10dp"
android:layout_marginRight="#dimen/margin10dp"
android:layout_weight="1"
android:clickable="false"
android:focusable="false"
android:focusableInTouchMode="false" />
<com.facebook.drawee.view.SimpleDraweeView
android:id="#+id/rightImage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:adjustViewBounds="true"
android:maxHeight="350dp"
fresco:actualImageScaleType="fitCenter"
fresco:placeholderImage="#color/white" />
</LinearLayout>
Update
As I was working on PDF to generate PDF from views, and was not able to generate PDF so I have posted this question.
But Now, I found a solution to generate PDF by using Webview you can see my answer on this question has marked as accepted.
Based on solution what I found, I have created a library to generate PDF from any String or Any HTML Content.
PDF-Generator Library: PDF-Generator
Thanks
I was looking at all the answers here, but unfortunately, they didn't work for me. I took the method for creating Bitmap from StackOverflow. The method takes the recycler view as an argument and converts it into a Bitmap which is then used by the PdfDocument.pageInfo to make it work for your needs. I tried it and it works perfectly for all the layouts such as relative layout and linear layout. Hope this will help.
Bitmap recycler_view_bm = getScreenshotFromRecyclerView(mRecyclerView);
try {
pdfFile.createNewFile();
FileOutputStream fOut = new FileOutputStream(pdfFile);
PdfDocument document = new PdfDocument();
PdfDocument.PageInfo pageInfo = new
PdfDocument.PageInfo.Builder(recycler_view_bm.getWidth(), recycler_view_bm.getHeight(), 1).create();
PdfDocument.Page page = document.startPage(pageInfo);
recycler_view_bm.prepareToDraw();
Canvas c;
c = page.getCanvas();
c.drawBitmap(recycler_view_bm,0,0,null);
document.finishPage(page);
document.writeTo(fOut);
document.close();
Snackbar snackbar = Snackbar
.make(equipmentsRecordActivityLayout, "PDF generated successfully.", Snackbar.LENGTH_LONG)
.setAction("Open", new View.OnClickListener() {
#Override
public void onClick(View view) {
openPDFRecord(pdfFile);
}
});
snackbar.show();
} catch (IOException e) {
e.printStackTrace();
}
}
public Bitmap getScreenshotFromRecyclerView(RecyclerView view) {
RecyclerView.Adapter adapter = view.getAdapter();
Bitmap bigBitmap = null;
if (adapter != null) {
int size = adapter.getItemCount();
int height = 0;
Paint paint = new Paint();
int iHeight = 0;
final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
// Use 1/8th of the available memory for this memory cache.
final int cacheSize = maxMemory / 8;
LruCache<String, Bitmap> bitmaCache = new LruCache<>(cacheSize);
for (int i = 0; i < size; i++) {
RecyclerView.ViewHolder holder = adapter.createViewHolder(view, adapter.getItemViewType(i));
adapter.onBindViewHolder(holder, i);
holder.itemView.measure(View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
holder.itemView.layout(0, 0, holder.itemView.getMeasuredWidth(), holder.itemView.getMeasuredHeight());
holder.itemView.setDrawingCacheEnabled(true);
holder.itemView.buildDrawingCache();
Bitmap drawingCache = holder.itemView.getDrawingCache();
if (drawingCache != null) {
bitmaCache.put(String.valueOf(i), drawingCache);
}
height += holder.itemView.getMeasuredHeight();
}
bigBitmap = Bitmap.createBitmap(view.getMeasuredWidth(), height, Bitmap.Config.ARGB_8888);
Canvas bigCanvas = new Canvas(bigBitmap);
bigCanvas.drawColor(Color.WHITE);
for (int i = 0; i < size; i++) {
Bitmap bitmap = bitmaCache.get(String.valueOf(i));
bigCanvas.drawBitmap(bitmap, 0f, iHeight, paint);
iHeight += bitmap.getHeight();
bitmap.recycle();
}
}
return bigBitmap;
}
Here is a samble code of generating a PDF from a view
//create bitmap from view and returns it
private Bitmap getBitmapFromView(View view) {
ScrollView hsv = (ScrollView) findViewById(R.id.scrollViewP);
HorizontalScrollView horizontal = (HorizontalScrollView) findViewById(R.id.hsv);
int totalHeight = hsv.getChildAt(0).getHeight();
int totalWidth = horizontal.getChildAt(0).getWidth();
Bitmap returnedBitmap = Bitmap.createBitmap(totalWidth, totalHeight,Bitmap.Config.ARGB_8888);
//Bind a canvas to it
Canvas canvas = new Canvas(returnedBitmap);
//Get the view's background
Drawable bgDrawable =view.getBackground();
if (bgDrawable!=null) {
//has background drawable, then draw it on the canvas
bgDrawable.draw(canvas);
} else{
//does not have background drawable, then draw white background on the canvas
canvas.drawColor(Color.WHITE);
}
// draw the view on the canvas
view.draw(canvas);
//return the bitmap
return returnedBitmap;
}
private static void addImage(Document document,byte[] byteArray)
{
Image image = null;
try
{
image = Image.getInstance(byteArray);
}
catch (BadElementException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (MalformedURLException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
// image.scaleAbsolute(150f, 150f);
try
{
document.add(image);
} catch (DocumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void CreatePDF()
{
File folder = new File(Environment.getExternalStorageDirectory()+File.separator+"PDF Folder");
folder.mkdirs();
Date date = new Date() ;
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(date);
final File myFile = new File(folder + timeStamp + ".pdf");
try {
OutputStream output = new FileOutputStream(myFile);
Document document = new Document(PageSize.A4);
try{
PdfWriter.getInstance(document, output);
document.open();
LinearLayout view2 = (LinearLayout)findViewById(R.id.MainLayout);
view2.setDrawingCacheEnabled(true);
Bitmap screen2= getBitmapFromView(view2);
ByteArrayOutputStream stream2 = new ByteArrayOutputStream();
screen2.compress(Bitmap.CompressFormat.JPEG,100, stream2);
byte[] byteArray2 = stream2.toByteArray();
addImage(document,byteArray2);
document.close();
AlertDialog.Builder builder = new AlertDialog.Builder(PaySlip.this, R.style.AppCompatAlertDialogStyle);
builder.setTitle("Success")
.setMessage("enter code herePDF File Generated Successfully.")
.setIcon(android.R.drawable.ic_dialog_alert)
.setPositiveButton(android.R.string.ok,new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton)
{
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(myFile), "application/pdf");
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(intent);
}
}).show();
//document.add(new Paragraph(mBodyEditText.getText().toString()));
}catch (DocumentException e)
{
//loading.dismiss();
e.printStackTrace();
}
}catch (FileNotFoundException e)
{
// loading.dismiss();
e.printStackTrace();
}
}
Where view is the instance of RecyclerView:
view.measure(
View.MeasureSpec.makeMeasureSpec(view.getWidth(), View.MeasureSpec.EXACTLY),
View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
myBitmap = Bitmap.createBitmap(view.getWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888);
After lots of workaround and solutions i got solution, and Best approach to achieve this,
Add your content in webview in html form, From webview we can directly do print using Android's PrintManager class.
Like this :
String documentName = "yourDocumentName"; // you can provide any name
// Get a PrintManager instance
PrintManager printManager = (PrintManager) context.getSystemService(PRINT_SERVICE);
// Get a print adapter instance
PrintDocumentAdapter printAdapter = webView.createPrintDocumentAdapter(documentName);
PrintJob printJob = printManager.print(documentName, printAdapter, new PrintAttributes.Builder().build());
Above is sample code to do print of webview content, using this we can also generate PDF too.
For more info and use refer this Printing HTML Document
Thanks.
UPDATES: Even if i don't retrieve images from cache, i tried to retrieve via Drawable where i stored all the 18 images in the "drawable-mdpi" folder. Still, a blank screen was display.
I was able to retrieved images from the server and save the image (.GIF) into the cache. However, when i need to load that image from cache, the image doesn't show up on screen. Here is the codes that does the work:
File cacheDir = context.getCacheDir();
File cacheMap = new File(cacheDir, smallMapImageNames.get(i).toString());
if(cacheMap.exists()){
FileInputStream fis = null;
try {
fis = new FileInputStream(cacheMap);
Bitmap local = BitmapFactory.decodeStream(fis);
puzzle.add(local);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}else{
Drawable smallMap = LoadImageFromWebOperations(mapPiecesURL.get(i).toString());
if(i==0){
height1 = smallMap.getIntrinsicHeight();
width1 = smallMap.getIntrinsicWidth();
}
if (smallMap instanceof BitmapDrawable) {
Bitmap bitmap = ((BitmapDrawable)smallMap).getBitmap();
FileOutputStream fos = null;
try {
cacheMap.createNewFile();
fos = new FileOutputStream(cacheMap);
bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
puzzle.add(bitmap);
}
}
ArrayList to store the image names: smallMapImageNames (The image names can also be found in the URL)
ArrayList to store the URL of the images: mapPiecesURL
To sum it up i have 2 questions
1) how to load images from cache?
2) regarding the bitmap.compress(), the images from the server is .GIF format but i apply Bitmap.CompressFormat.PNG. So is there going to be any problem with this?
Can anyone please help me with this?
The two functions
private Bitmap getBitMap(Context context) {
// TODO Auto-generated method stub
WifiPositioningServices wifiPositioningServices = new WifiPositioningServices();
String[] mapURLandCalibratedPoint1 = wifiPositioningServices.GetMapURLandCalibratedPoint("ERLab-1_1.GIF","ERLab"); //list of map pieces url in the first 9 pieces
String[] mapURLandCalibratedPoint2 = wifiPositioningServices.GetMapURLandCalibratedPoint("ERLab-4_1.GIF","ERLab"); //list of map pieces url in the last 9 pieces
ArrayList<String> smallMapImageNames = new ArrayList<String>();
ArrayList<String> mapPiecesURL = new ArrayList<String>();
for(int i=0; i<mapURLandCalibratedPoint1.length; i++){
if(mapURLandCalibratedPoint1[i].length()>40){ //image url
int len = mapURLandCalibratedPoint1[i].length();
int subStrLen = len-13;
smallMapImageNames.add(mapURLandCalibratedPoint1[i].substring(subStrLen, len-3)+"JPEG");
mapPiecesURL.add(mapURLandCalibratedPoint1[i]);
}
else{
//perform other task
}
}
for(int i=0; i<mapURLandCalibratedPoint2.length; i++){
if(mapURLandCalibratedPoint2[i].length()>40){ //image url
int len = mapURLandCalibratedPoint2[i].length();
int subStrLen = len-13;
smallMapImageNames.add(mapURLandCalibratedPoint2[i].substring(subStrLen, len-3)+"JPEG");
mapPiecesURL.add(mapURLandCalibratedPoint2[i]);
}
else{
//perform other task
}
}
Bitmap result = Bitmap.createBitmap(1029, 617, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(result);
ArrayList<Bitmap> puzzle = new ArrayList<Bitmap>();
int height1 = 0 ;
int width1 = 0;
File cacheDir = context.getCacheDir();
for(int i=0; i<18; i++){
File cacheMap = new File(cacheDir, smallMapImageNames.get(i).toString());
if(cacheMap.exists()){
//retrieved from cached
try {
FileInputStream fis = new FileInputStream(cacheMap);
Bitmap bitmap = BitmapFactory.decodeStream(fis);
puzzle.add(bitmap);
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}else{
//retrieve from server and cached it
Drawable smallMap = LoadImageFromWebOperations(mapPiecesURL.get(i).toString());
if(i==0){
height1 = smallMap.getIntrinsicHeight();
width1 = smallMap.getIntrinsicWidth();
}
if (smallMap instanceof BitmapDrawable) {
Bitmap bitmap = ((BitmapDrawable)smallMap).getBitmap();
FileOutputStream fos = null;
try {
cacheMap.createNewFile();
fos = new FileOutputStream(cacheMap);
bitmap.compress(CompressFormat.JPEG, 100, fos);
fos.flush();
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
puzzle.add(bitmap);
}
}
}
Rect srcRect;
Rect dstRect;
int cnt =0;
for (int j = 0; j < 3; j++) {
int newHeight = height1 * (j % 3);
for (int k = 0; k < 3; k++) {
if (j == 0 && k == 0) {
srcRect = new Rect(0, 0, width1, height1);
dstRect = new Rect(srcRect);
} else {
int newWidth = width1 * k;
srcRect = new Rect(0, 0, width1, height1);
dstRect = new Rect(srcRect);
dstRect.offset(newWidth, newHeight);
}
canvas.drawBitmap(puzzle.get(cnt), srcRect, dstRect,null);
cnt++;
}
}
for(int a=0; a<3; a++){
int newHeight = height1 * (a % 3);
for (int k = 3; k < 6; k++) {
if (a == 0 && k == 0) {
srcRect = new Rect(0, 0, width1*3, height1);
dstRect = new Rect(srcRect);
} else {
int newWidth = width1 * k;
srcRect = new Rect(0, 0, width1, height1);
dstRect = new Rect(srcRect);
dstRect.offset(newWidth, newHeight);
}
canvas.drawBitmap(puzzle.get(cnt), srcRect, dstRect,
null);
cnt++;
}
}
return result;
}
private Drawable LoadImageFromWebOperations(String url) {
// TODO Auto-generated method stub
try
{
InputStream is = (InputStream) new URL(url).getContent();
Drawable d = Drawable.createFromStream(is, "src name");
return d;
}catch (Exception e) {
System.out.println("Exc="+e);
return null;
}
}
I am actually trying to display 18 pieces (3X6) of images to form up a floorplan. So to display the images, i use two for-loop to display it. the two .GIF images, ERLab-1_1.GIF and ERLab-4_1.GIF are the center piece of each group. For example, the first row of would be ERLab-0_0.GIF, ERLab-1_0.GIF, ERLab-2_0.GIF, ERLab-3_0.GIF, ERLab-4_0.GIF, ERLab-5_0.GIF. Second row would be XXX-X_1.GIF and XXX-X_2.GIF for the third row.
Lastly,
Bitmap resultMap = getBitMap(this.getContext());
bmLargeImage = Bitmap.createBitmap(1029 , 617, Bitmap.Config.ARGB_8888);
bmLargeImage = resultMap;
Then in the onDraw function would be drawing the image onto the canvas.
I just solved my own question.
In this line, canvas.drawBitmap(puzzle.get(cnt), srcRect, dstRect,null); within each of the for-loop which i am using it to draw the bitmap onto the canvas, i need to cast the each item in the ArrayList (puzzle) to Bitmap. Only then will the image get display.
I thought that if the ArrayList is definite as such, ArrayList<Bitmap> puzzle = new ArrayList<Bitmap>(); each items in the ArrayList would be of Bitmap type. But isn't that always true?