Reputation: 2127
I'm trying to populate a LinearLayout
inside simple_pdf_example.xml
with 10 printed_order_element2.xml
just so I can generate a PDF with a ListView
(which is actually a LinearLayout
).
The problem is that when I do linearLayoutView.addView(v)
10 times, I don't see v
inside the LinearLayout
. I just see the original item I added in the xml just to see if the LinearLayout
was rendering.
SimplePDFSaver.java:
package com.mypackage.example;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.FileProvider;
import android.content.Intent;
import android.graphics.pdf.PdfDocument;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import java.io.File;
import java.io.FileOutputStream;
public class SimplePDFSaver extends AppCompatActivity {
private static final String TAG = "SimplePDFSaver";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_simple_pdfsaver);
generatePDF();
}
public void generatePDF() {
LayoutInflater inflater = getLayoutInflater();
View pdfLayout = inflater.inflate(R.layout.simple_pdf_example,
findViewById(android.R.id.content),
false);
int sizeSpec = View.MeasureSpec.makeMeasureSpec(2480, View.MeasureSpec.EXACTLY);
int sizeSpec2 = View.MeasureSpec.makeMeasureSpec(3508, View.MeasureSpec.EXACTLY);
pdfLayout.measure(sizeSpec, sizeSpec2);
int width = pdfLayout.getMeasuredWidth();
int height = pdfLayout.getMeasuredHeight();
pdfLayout.layout(0, 0, width, height);
LinearLayout linearLayoutView = pdfLayout.findViewById(R.id.linearLayoutView);
for (int i=0; i<10; i++) {
View v = getLayoutInflater().inflate(R.layout.printed_order_element2, null);
linearLayoutView.addView(v);
}
Runnable r = new Runnable() {
@Override
public void run() {
PdfDocument document = new PdfDocument();
PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(2480, 3508, 0).create();
PdfDocument.Page page = document.startPage(pageInfo);
pdfLayout.draw(page.getCanvas());
document.finishPage(page);
FileOutputStream outStream;
File file = new File(getExternalFilesDir(null), "file.pdf");
try {
outStream = new FileOutputStream(file);
document.writeTo(outStream);
document.close();
outStream.flush();
outStream.getFD().sync();
outStream.close();
Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = FileProvider.getUriForFile(SimplePDFSaver.this, BuildConfig.APPLICATION_ID + ".provider", file);
intent.setDataAndType(uri, "application/pdf");
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(intent);
} catch (Exception e) {
e.printStackTrace();
Log.d(TAG, e.toString());
}
}
};
new Thread(r).start();
}
}
simple_pdf_example.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:id="@+id/linearLayoutView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:orientation="vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView10">
<TextView
android:id="@+id/textView13"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Just to see if linearLayoutView rendered" />
</LinearLayout>
<TextView
android:id="@+id/textView10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="There should be a list of items below:"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
printed_order_element2.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">
<TextView
android:id="@+id/textView6"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView" />
</LinearLayout>
This is what I get:
Upvotes: 4
Views: 5625
Reputation: 2127
Simply adding
pdfLayout.measure(sizeSpec, sizeSpec2);
pdfLayout.layout(0, 0, width, height);
after the for
loop fixed everything. Thanks to Ben P. https://stackoverflow.com/users/8298909/ben-p
The problem is that the layout needs to me measured or layout() must be executed. I don't know for sure, but it has to do with it. I don't know if the 2 lines are needed but you can try to use only one and see what works
Upvotes: 0
Reputation: 54194
I believe the problem lies in this section of code:
public void generatePDF() { LayoutInflater inflater = getLayoutInflater(); View pdfLayout = inflater.inflate(R.layout.simple_pdf_example, findViewById(android.R.id.content), false);
All of the rest of your code uses this inflated pdfLayout
view:
LinearLayout linearLayoutView = pdfLayout.findViewById(R.id.linearLayoutView); for (int i=0; i<10; i++) { View v = getLayoutInflater().inflate(R.layout.printed_order_element2, null); linearLayoutView.addView(v); }
pdfLayout.draw(page.getCanvas());
The problem is that your pdfLayout
view is never put on the screen. Your setContentView()
call in onCreate()
inflates a different layout, and the inflated pdfLayout
is never attached to any view!
When you call inflate(int, View, boolean)
and pass false
as the third argument, you are telling the system to treat the second argument (the View
) as the parent only in order to parse LayoutParams
on the root of the inflated layout. The inflated layout is not added to the parent! You have to manually call parent.addView()
with the inflated view.
How to fix it? It's hard to say, exactly, since I've got a few questions. But maybe just asking the questions will reveal the answer.
It's strange to see both a call to setContentView()
and a call to inflate()
that passes in android.R.id.content
as the parent. Could you just call setContentView(R.layout.simple_pdf_example)
in your onCreate()
, and avoid the second inflate()
call altogether?
If so, then you'd replace all calls to pdfLayout.findViewById()
with direct findViewById()
calls (since what was previously pdfLayout
is now just your Activity's main content).
Upvotes: 2
Reputation: 3659
Your linearLayoutView lies in pdfLayout, but when you inflate pdfLayout you don't add it to the parent. Please, try this way:
View pdfLayout = inflater.inflate(R.layout.simple_pdf_example, findViewById(android.R.id.content));
Upvotes: 1