Home > Java > body text

How to get the total height of a view

PHPz
Release: 2024-02-06 08:35:07
forward
635 people have browsed it
Question content

I need to get the total height of the view to generate a PDF to know how many pages need to be drawn.

I need to generate a PDF using screen content, which has a ScrollView containing data from a database.

I created a test project for this, see the code below.

Even if I change the XML to add more images, this code always gives me the same number:

ViewTreeObserver vto2 = layout.getViewTreeObserver();
        vto2.addOnGlobalLayoutListener (new ViewTreeObserver.OnGlobalLayoutListener() {
            @Override
            public void onGlobalLayout() {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                    layout.getViewTreeObserver()
                            .removeOnGlobalLayoutListener(this);
                } else {
                    layout.getViewTreeObserver()
                            .removeGlobalOnLayoutListener(this);
                }
                int width  = layout.getMeasuredWidth();
                int height = layout.getMeasuredHeight();

            }
        });
Copy after login

This is my code to generate PDF:

public void convertXmlToPdf() {

        PdfDocument document = new PdfDocument();
        DisplayMetrics displayMetrics = new DisplayMetrics();

        int viewWidth = 1080;
        int viewHeight = 1920;

        int numPagina = 1;
        View view = LayoutInflater.from(this).inflate(R.layout.main_activity, null);

        view.measure(View.MeasureSpec.makeMeasureSpec(displayMetrics.widthPixels, View.MeasureSpec.EXACTLY),
                View.MeasureSpec.makeMeasureSpec(displayMetrics.heightPixels * numPagina, View.MeasureSpec.EXACTLY));
        view.getMeasuredHeight();

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            this.getDisplay().getRealMetrics(displayMetrics);
        } else
            this.getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        if(ViewCompat.isLaidOut(view)) {
            view.getHeight();
        }
        view.layout(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels);

        Display display = getWindowManager().getDefaultDisplay();
        Point m_size = new Point();
        display.getSize(m_size);

        int m_height = m_size.y;

        **double totalPages = Math.ceil(Double.parseDouble(m_height + "") / Double.parseDouble(viewHeight + "")); //TODO <----- i can't get the real height number here**
//        double totalPages = 4;

        do {
            view = LayoutInflater.from(this).inflate(R.layout.main_activity, null);

            if(numPagina == 1) {
                view.measure(View.MeasureSpec.makeMeasureSpec(displayMetrics.widthPixels, View.MeasureSpec.EXACTLY),
                        View.MeasureSpec.makeMeasureSpec(displayMetrics.heightPixels * numPagina, View.MeasureSpec.EXACTLY));
            } else {
                view.measure(View.MeasureSpec.makeMeasureSpec(displayMetrics.widthPixels, View.MeasureSpec.EXACTLY),
                        View.MeasureSpec.makeMeasureSpec(displayMetrics.heightPixels * numPagina + (displayMetrics.heightPixels * numPagina - displayMetrics.heightPixels), View.MeasureSpec.EXACTLY)); //If i don't do this the next pages don't start from where they need
            }
            view.layout(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels);
            // Create a new PdfDocument instance

            view.getMeasuredHeight();

            PdfDocument.PageInfo pageInfo = new PdfDocument.PageInfo.Builder(displayMetrics.widthPixels, displayMetrics.heightPixels, numPagina).create();

            // Start a new page
            PdfDocument.Page page = document.startPage(pageInfo);

            // Get the Canvas object to draw on the page
            Canvas canvas = page.getCanvas();

            // Create a Paint object for styling the view
            Paint paint = new Paint();
            paint.setColor(Color.BLACK);

            // Draw the view on the canvas
            view.draw(canvas);

            // Finish the page
            document.finishPage(page);
            numPagina++;
        } while (numPagina <= totalPages);


        // Specify the path and filename of the output PDF file
        File downloadsDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);
        String fileName = "exampleXML.pdf";
        File filePath = new File(downloadsDir, fileName);

        try {
            // Save the document to a file
            FileOutputStream fos = new FileOutputStream(filePath);
            document.writeTo(fos);
            document.close();
            fos.close();
            // PDF conversion successful
            Toast.makeText(this, "XML to PDF Conversion Successful", Toast.LENGTH_LONG).show();
        } catch (IOException e) {
            e.printStackTrace();
            // Error occurred while converting to PDF
        }
    }
Copy after login

This is my XML file:

<?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:gravity="center"
    android:orientation="vertical"
    android:id="@+id/rootview">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:text="Learn to Create PDF"
        android:textStyle="bold"
        android:textColor="@color/black"/>


    <Button
        android:id="@+id/btnCreatePdf"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Create PDF" />

    <Button
        android:id="@+id/btnXMLToPDF"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Convert XML View to PDF" />

    <ScrollView
        android:layout_width="wrap_content"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:padding="30px"
                android:text="1"
                android:textColor="@color/black" />

            <ImageView
                android:id="@+id/image"
                android:layout_width="wrap_content"
                android:layout_height="360px"
                android:src="@drawable/logo_om"
                android:visibility="visible" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:padding="30px"
                android:text="2"
                android:textColor="@color/black"/>

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="360px"
                android:src="@drawable/logo_om"
                android:visibility="visible" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:padding="30px"
                android:text="3"
                android:textColor="@color/black"/>


            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="360px"
                android:src="@drawable/logo_om"
                android:visibility="visible" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:padding="30px"
                android:text="4"
                android:textColor="@color/black"/>

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="360px"
                android:src="@drawable/logo_om"
                android:visibility="visible" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:padding="30px"
                android:text="5"
                android:textColor="@color/black" />

            <ImageView
                android:layout_width="wrap_content"
                android:layout_height="360px"
                android:src="@drawable/logo_om"
                android:visibility="visible" />

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:padding="30px"
                android:text="FINAL DO DOCUMENTO" />

        </LinearLayout>

    </ScrollView>


</LinearLayout>
Copy after login

@edit: Here are the links to what I've tried: Android: Total height of ScrollView

How to tell when the layout is drawn?

@Edit2: Here is a tutorial for creating a PDF (it only generates 1 page, so the code to generate more pages is what I found around) https://www.youtube.com/watch?v=-JC1PI-dSeE


Correct Answer


The code always gives you the same number as you told It gives you whatever number it wants, and fixes the number to the size you tell it to give it.

When you set Measurespec to EXACTLY according to the documentation

So you are forcing the view size to an incorrect size calculated based on the screen size.

When drawing a PDF view, you can set the PDF page to an interesting size that matches your screen, or you can set it to a standard paper size, such as A4

If you choose non-standard width, you can also use non-standard height and only have one page. Then, if the user wanted to print it, they would have to split it into pages of multiple widths and heights. From a user perspective, there is no benefit to using multiple pages if you are just viewing the PDF on the screen

I think it's better to stick with the standard page size of the PDF, and then treat the PDF as a separate low-resolution screen, independent of the physical screen size of the device (they can scroll the page up, down, left, and right)

When you measure a single view, you are measuring the entire view and all its subviews, you cannot measure slices (what you want to see on the second and third pages).

There are two main ways to create multi-page PDFs from views.

  1. Draw everything and then slice and dice it across multiple pages, using this approach you might have items that are split between pages, like the top half of certain lines of text on one page and The bottom half on another page makes it unreadable. This is not a good approach.

  2. Iterate over the parent view's subviews, measure each subview, and add them to the layout of a single page. This way you can get the size of each subview and then calculate the cumulative size of all the views you've added to see if it's too big for your page size. If it's too big, you'll close the PDF page and start laying out to a new page. This means items are not split across pages (which is much better).

https://www.php.cn/link/ea89621bee7c88b2c5be6681c8ef4906 is a complete example of how to generate a multi-page PDF from a scrollable screen by measuring individual subviews (in this case, A scrollable screen is a recycling view, but you can iterate over the scroll view's children in a similar way).

Please note that A4 pages have a very low resolution, so the normal font size (or other item size) for the physical screen may be too large, so you will need to resize the layout for these as you normally would for different screen sizes). There is another way to resize a PDF page for low resolution, draw it to a multiple of the PDF page size, and then set the scale on the PDF canvas to scale it back to the correct size, e.g. draw to a layout that is twice as big, Then scale everything back to half size when drawing to the PDF page.

While the problem you may encounter is that your Textview may contain more text in a block than can fit on one page, these should require additional processing to create two Textviews instead of one.

The above is the detailed content of How to get the total height of a view. For more information, please follow other related articles on the PHP Chinese website!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!