Kotlin Generate PDF From View Convert Activity XML Layout ScrollView

kotlin take scrollview screenshot, kotlin generate pdf from view, kotlin take screenshot, kotlin custom camera, kotlin indeterminate horizontal progressbar, kotlin horizontal recyclerview, Kotlin Volley ListView JSON, Kotlin RecyclerView Volley

Learn on Kotlin Generate PDF From View Convert Activity XML Layout ScrollView.

In this example, you will see how to convert your any view or layout into the PDF file.

Other than XML or activity view layout, we will also learn how to convert scroll view into the PDF file.

We will do all these things using the Kotlin as the primary language of android studio project.

First of all, see the following output material.

 

Step 1. Gradle and Manifest Changes

Make a new project in the android studio with kotlin as the source language and empty activity.

Now go to AndroidManifest.xml file and add the below lines in it

 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

These are defining READ and WRITE permissions for our app. We also need to implement runtime permissions. We will do this later in the Main Activity file.

Now write the following line in build.gradle(Module:app) file.

 implementation 'com.karumi:dexter:5.0.0'

Above line will add the dexter library into our android studio project. This library will help us for runtime permissions.

In this file you need to set minSdkVersion as 19. See the below line

minSdkVersion 19

So, final source code for build.gradle(Module:app) file is as the below

apply plugin: 'com.android.application'

apply plugin: 'kotlin-android'

apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.example.pdffromviewkotlin"
        minSdkVersion 19
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'

    implementation 'com.karumi:dexter:5.0.0'

}

Step 2. Main Files

In your activity_main.xml file, you should add the following

<?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:background="#ffffff"
              android:orientation="vertical">

    <LinearLayout
            android:id="@+id/llPdf"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="#fff"
            android:orientation="vertical">

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

        <ImageView
                android:id="@+id/iv"
                android:layout_width="300dp"
                android:layout_height="200dp"
                android:layout_marginLeft="30dp"
                android:layout_marginTop="10dp"
                android:src="@drawable/pyramid" />

        <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="30dp"
                android:layout_marginTop="10dp"
                android:text="Pyramid from Egypt"
                android:textSize="30sp" />

        <Button
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:id="@+id/btnScroll"
                android:layout_marginTop="20dp"
                android:layout_marginLeft="20dp"
                android:text="Make PDF Of ScrollView"/>

    </LinearLayout>


</LinearLayout>

There is one Image view and one text view is present. Image view is previewing the image of pyramid.

Text view has some text which can not be changed from Kotlin file.

There are two buttons in the above file : CREATE PDF and MAKE PDF OF SCROLL VIEW

Now in your MainActivity.kt file, write down the below source snippet

import android.Manifest
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.pdf.PdfDocument
import android.os.Build
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.support.annotation.RequiresApi
import android.util.DisplayMetrics
import android.util.Log
import android.view.View
import android.view.WindowManager
import android.widget.Button
import android.widget.LinearLayout
import android.widget.Toast
import com.karumi.dexter.Dexter
import com.karumi.dexter.MultiplePermissionsReport
import com.karumi.dexter.PermissionToken
import com.karumi.dexter.listener.DexterError
import com.karumi.dexter.listener.PermissionRequest
import com.karumi.dexter.listener.PermissionRequestErrorListener
import com.karumi.dexter.listener.multi.MultiplePermissionsListener
import java.io.File
import java.io.FileOutputStream
import java.io.IOException

class MainActivity : AppCompatActivity() {

    private var btn: Button? = null
    private var btnScroll: Button? = null
    private var llPdf: LinearLayout? = null
    private var bitmap: Bitmap? = null
    var targetPdf: String = "/storage/emulated/0//pdffromlayoutview.pdf"

    @RequiresApi(Build.VERSION_CODES.KITKAT)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        requestReadPermissions()

        btn = findViewById(R.id.btn)
        btnScroll = findViewById(R.id.btnScroll)
        llPdf = findViewById(R.id.llPdf)

        btnScroll!!.setOnClickListener {
            val intent = Intent(this@MainActivity, ScrollActivity::class.java)
            startActivity(intent)
        }

        btn!!.setOnClickListener {
            Log.d("size", " " + llPdf!!.width + "  " + llPdf!!.width)
            bitmap = loadBitmapFromView(llPdf!!, llPdf!!.width, llPdf!!.height)
            createPdf()
        }

    }

    private fun createPdf() {
        val wm = getSystemService(Context.WINDOW_SERVICE) as WindowManager
        //  Display display = wm.getDefaultDisplay();
        val displaymetrics = DisplayMetrics()
        this.windowManager.defaultDisplay.getMetrics(displaymetrics)
        val hight = displaymetrics.heightPixels.toFloat()
        val width = displaymetrics.widthPixels.toFloat()

        val convertHighet = hight.toInt()
        val convertWidth = width.toInt()

        val document = PdfDocument()
        val pageInfo = PdfDocument.PageInfo.Builder(convertWidth, convertHighet, 1).create()
        val page = document.startPage(pageInfo)

        val canvas = page.canvas

        val paint = Paint()
        canvas.drawPaint(paint)

        bitmap = Bitmap.createScaledBitmap(bitmap!!, convertWidth, convertHighet, true)

        paint.color = Color.BLUE
        canvas.drawBitmap(bitmap!!, 0f, 0f, null)
        document.finishPage(page)

        // write the document content

        Log.d("target",targetPdf)
        val filePath: File
        filePath = File(targetPdf)
        try {
            document.writeTo(FileOutputStream(filePath))

        } catch (e: IOException) {
            e.printStackTrace()
            Toast.makeText(this, "Something wrong: $e", Toast.LENGTH_LONG).show()
        }

        // close the document
        document.close()
        Toast.makeText(this, "PDF is created!!!", Toast.LENGTH_SHORT).show()

    }

    companion object {

        fun loadBitmapFromView(v: View, width: Int, height: Int): Bitmap {
            val b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
            val c = Canvas(b)
            v.draw(c)

            return b
        }
    }

    private fun requestReadPermissions() {

        Dexter.withActivity(this)
            .withPermissions( Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE )
            .withListener(object : MultiplePermissionsListener {
                override fun onPermissionsChecked(report: MultiplePermissionsReport) {
                    // check if all permissions are granted
                    if (report.areAllPermissionsGranted()) {
                        Toast.makeText(applicationContext, "All permissions are granted by user!", Toast.LENGTH_SHORT)
                            .show()
                    }

                    // check for permanent denial of any permission
                    if (report.isAnyPermissionPermanentlyDenied) {
                        // show alert dialog navigating to Settings
                        //openSettingsDialog();
                    }
                }

                override fun onPermissionRationaleShouldBeShown(permissions: List<PermissionRequest>, token: PermissionToken) {
                    token.continuePermissionRequest()
                }
            }).withErrorListener(object : PermissionRequestErrorListener {
                override fun onError(error: DexterError) {
                    Toast.makeText(applicationContext, "Some Error! ", Toast.LENGTH_SHORT).show()
                }
            })
            .onSameThread()
            .check()
    }

}

Deep Learn

First of all, see the following

  private var btn: Button? = null
    private var btnScroll: Button? = null
    private var llPdf: LinearLayout? = null
    private var bitmap: Bitmap? = null
    var targetPdf: String = "/storage/emulated/0//pdffromlayoutview.pdf"

Compiler will first make the objects of the button classes. Then there the objects of LinearLayout and Bitmap classes.

After this, it will define one String variable targetPdf . This variable holds the path to the PDF file.

Inside onCreate() method, there is another function called requestReadPermissions()

Below is the source code for requestReadPermissions() method.

  private fun requestReadPermissions() {

        Dexter.withActivity(this)
            .withPermissions( Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE )
            .withListener(object : MultiplePermissionsListener {
                override fun onPermissionsChecked(report: MultiplePermissionsReport) {
                    // check if all permissions are granted
                    if (report.areAllPermissionsGranted()) {
                        Toast.makeText(applicationContext, "All permissions are granted by user!", Toast.LENGTH_SHORT)
                            .show()
                    }

                    // check for permanent denial of any permission
                    if (report.isAnyPermissionPermanentlyDenied) {
                        // show alert dialog navigating to Settings
                        //openSettingsDialog();
                    }
                }

                override fun onPermissionRationaleShouldBeShown(permissions: List<PermissionRequest>, token: PermissionToken) {
                    token.continuePermissionRequest()
                }
            }).withErrorListener(object : PermissionRequestErrorListener {
                override fun onError(error: DexterError) {
                    Toast.makeText(applicationContext, "Some Error! ", Toast.LENGTH_SHORT).show()
                }
            })
            .onSameThread()
            .check()
    }

This method is helping us to implement the runtime permissions. In this task, dexter library will help us.

We are asking for READ and WRIGHT permissions in this method.

Now read the following code

  btnScroll!!.setOnClickListener {
            val intent = Intent(this@MainActivity, ScrollActivity::class.java)
            startActivity(intent)
        }

Compiler will run the above code when the user clicks “MAKE PDF OF SCROLL VIEW” button.

It will simply open the ScrollActivity. We will create this activity in the next step.

Now compiler will run the following on the click event of CREATE PDF button.

   btn!!.setOnClickListener {
            Log.d("size", " " + llPdf!!.width + "  " + llPdf!!.width)
            bitmap = loadBitmapFromView(llPdf!!, llPdf!!.width, llPdf!!.height)
            createPdf()
        }

Here, compiler will get the bitmap of the whole view or layout. For this, it will use loadBitmapFromView() method.

A method named createPdf() will use this bitmap to make the PDF file from this bitmap.

Below are the coding lines for createPdf() function.

 private fun createPdf() {
        val wm = getSystemService(Context.WINDOW_SERVICE) as WindowManager
        //  Display display = wm.getDefaultDisplay();
        val displaymetrics = DisplayMetrics()
        this.windowManager.defaultDisplay.getMetrics(displaymetrics)
        val hight = displaymetrics.heightPixels.toFloat()
        val width = displaymetrics.widthPixels.toFloat()

        val convertHighet = hight.toInt()
        val convertWidth = width.toInt()

        val document = PdfDocument()
        val pageInfo = PdfDocument.PageInfo.Builder(convertWidth, convertHighet, 1).create()
        val page = document.startPage(pageInfo)

        val canvas = page.canvas

        val paint = Paint()
        canvas.drawPaint(paint)

        bitmap = Bitmap.createScaledBitmap(bitmap!!, convertWidth, convertHighet, true)

        paint.color = Color.BLUE
        canvas.drawBitmap(bitmap!!, 0f, 0f, null)
        document.finishPage(page)

        // write the document content

        Log.d("target",targetPdf)
        val filePath: File
        filePath = File(targetPdf)
        try {
            document.writeTo(FileOutputStream(filePath))

        } catch (e: IOException) {
            e.printStackTrace()
            Toast.makeText(this, "Something wrong: $e", Toast.LENGTH_LONG).show()
        }

        // close the document
        document.close()
        Toast.makeText(this, "PDF is created!!!", Toast.LENGTH_SHORT).show()

    }

This method is using various classes like Canvas, Paint etc. to create the PDF file from XML layout.

Step 3. Making PDF from Scroll View

Make a new activity and give it a name like Scroll Activity. You should add the following in activity_scroll.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:background="#ffffff"
              android:orientation="vertical">

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

        <LinearLayout
                android:id="@+id/llScroll"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="#fff"
                android:orientation="vertical">

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

            <ImageView
                    android:id="@+id/iv"
                    android:layout_width="300dp"
                    android:layout_height="300dp"
                    android:layout_marginLeft="30dp"
                    android:layout_marginTop="10dp"
                    android:src="@drawable/empire" />

            <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="30dp"
                    android:layout_marginTop="10dp"
                    android:text="Empire state building is located in the New York, US"
                    android:textSize="30sp" />

            <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="30dp"
                    android:layout_marginTop="10dp"
                    android:text="Empire state building is located in the New York, US"
                    android:textSize="30sp" />

            <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginLeft="30dp"
                    android:layout_marginTop="10dp"
                    android:text="Empire state building is located in the New York, US"
                    android:textSize="30sp" />

        </LinearLayout>

    </ScrollView>

</LinearLayout>

Above file contains the scroll view as the parent. Inside scroll view, there is one button, one image view and three text views are present.

Now in your ScrollActivity.kt file, you need to write the below source snippet

import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.pdf.PdfDocument
import android.icu.util.Calendar
import android.media.MediaScannerConnection
import android.net.Uri
import android.os.Build
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.os.Environment
import android.support.annotation.RequiresApi
import android.util.DisplayMetrics
import android.util.Log
import android.view.View
import android.view.WindowManager
import android.widget.Button
import android.widget.LinearLayout
import android.widget.Toast
import java.io.ByteArrayOutputStream

import java.io.File
import java.io.FileOutputStream
import java.io.IOException

class ScrollActivity : AppCompatActivity() {

    private var btn: Button? = null
    private var llScroll: LinearLayout? = null
    private var bitmap: Bitmap? = null

    @RequiresApi(Build.VERSION_CODES.KITKAT)
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_scroll)

        btn = findViewById(R.id.btn)
        llScroll = findViewById(R.id.llScroll)

        btn!!.setOnClickListener {
            Log.d("size", " " + llScroll!!.width + "  " + llScroll!!.width)
            bitmap = loadBitmapFromView(llScroll!!, llScroll!!.width, llScroll!!.height)
            createPdf()
        }

    }

    @RequiresApi(Build.VERSION_CODES.KITKAT)
    private fun createPdf() {
        val wm = getSystemService(Context.WINDOW_SERVICE) as WindowManager
        //  Display display = wm.getDefaultDisplay();
        val displaymetrics = DisplayMetrics()
        this.windowManager.defaultDisplay.getMetrics(displaymetrics)
        val hight = displaymetrics.heightPixels.toFloat()
        val width = displaymetrics.widthPixels.toFloat()

        val convertHighet = hight.toInt()
        val convertWidth = width.toInt()

        //        Resources mResources = getResources();
        //        Bitmap bitmap = BitmapFactory.decodeResource(mResources, R.drawable.screenshot);

        val document = PdfDocument()
        val pageInfo = PdfDocument.PageInfo.Builder(convertWidth, convertHighet, 1).create()
        val page = document.startPage(pageInfo)

        val canvas = page.canvas

        val paint = Paint()
        canvas.drawPaint(paint)

        bitmap = Bitmap.createScaledBitmap(bitmap!!, convertWidth, convertHighet, true)

        paint.color = Color.BLUE
        canvas.drawBitmap(bitmap!!, 0f, 0f, null)
        document.finishPage(page)

        // write the document content
        val targetPdf = "/sdcard/pdffromScroll.pdf"
        val filePath: File
        filePath = File(targetPdf)
        try {
            document.writeTo(FileOutputStream(filePath))

        } catch (e: IOException) {
            e.printStackTrace()
            Toast.makeText(this, "Something wrong: $e", Toast.LENGTH_LONG).show()
        }

        // close the document
        document.close()
        Toast.makeText(this, "PDF of Scroll is created!!!", Toast.LENGTH_SHORT).show()

    }

    companion object {

        fun loadBitmapFromView(v: View, width: Int, height: Int): Bitmap {
            val b = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
            val c = Canvas(b)
            v.draw(c)

            return b
        }
    }

}

Process of creating the PDF file of the scroll view is the same as of we have done in the previous step for Main Activity.

First, compiler will create the bitmap of the scroll view using loadBitmapFromView() method.

Then it will use this bitmap to create the PDF file.

Compiler will run the createPdf() method, when the user clicks the button.

A PDF file from scroll view will have the name like pdffromScroll.pdf

 

Download For Kotlin Generate PDF From View

https://github.com/demonuts/Kotlin-Generate-PDF-From-View-Convert-Activity-XML-Layout-ScrollView