Kotlin Take Scrollview Screenshot Programmatically | Full/Long Activity Page

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

Read for Kotlin Take Scrollview Screenshot Programmatically.

We will cover how to take the screenshot of Full and Long Activity Page using Kotlin.

Many times, you need to use scroll view to cover all the information which are too large to set on the device screen.

Taking screen shot if this scroll view is difficult task as we need to cover all the part which are hidden into the screen.

You will learn to take the screen shot of this whole scroll view with easy and small code snippet in this example tutorial.

First of all, see the following youtube video for final result.

 

Step 1. Permission Tasks

Create a new project in android studio with the Kotlin as the source code language.

Now open up your AndroidManifest.xml file. Add the following lines in this file.

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

We have added two permissions : Read and Write external storage.

Now our work is not finished yet for permissions. We also need to ask for runtime permissions.

For this, go to build.gradle(Module: app) file, add the below line in it

implementation 'com.karumi:dexter:5.0.0'

Above line will integrate Dexter library in our project. It will enable us to use library classes directly in our Kotlin files.

Step 2. Important Lines

Now let us write important lines for this example. Go to activity_main.xml file and add the following

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical"
              tools:context=".MainActivity">

    <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/btn"
            android:text="Take Screenshot of below scrollview!"
            android:textSize="20sp" />

    <ScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/scroll">


        <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:id="@+id/ll"
                android:layout_marginTop="10dp"
                android:orientation="vertical">

            <TextView
                    android:layout_width="match_parent"
                    android:layout_height="80dp"
                    android:gravity="center"
                    android:text="First Text!!"
                    android:textSize="30sp"
                    android:textColor="#fff"
                    android:background="#205dd7"/>

            <ImageView
                    android:layout_width="match_parent"
                    android:layout_height="180dp"
                    android:layout_marginTop="10dp"
                    android:src="@drawable/benz"
                    android:scaleType="fitXY"/>

            <TextView
                    android:layout_width="match_parent"
                    android:layout_height="80dp"
                    android:layout_marginTop="10dp"
                    android:gravity="center"
                    android:text="Second Text!!"
                    android:textSize="30sp"
                    android:textColor="#fff"
                    android:background="#de0f39"/>

            <ImageView
                    android:layout_width="match_parent"
                    android:layout_height="180dp"
                    android:layout_marginTop="10dp"
                    android:src="@drawable/bike"
                    android:scaleType="fitXY"/>

            <TextView
                    android:layout_width="match_parent"
                    android:layout_height="80dp"
                    android:layout_marginTop="10dp"
                    android:gravity="center"
                    android:text="Third Text!!"
                    android:textSize="30sp"
                    android:textColor="#fff"
                    android:background="#09e936"/>

            <ImageView
                    android:layout_width="match_parent"
                    android:layout_height="180dp"
                    android:layout_marginTop="10dp"
                    android:src="@drawable/silver"
                    android:scaleType="fitXY"/>


        </LinearLayout>

    </ScrollView>

</LinearLayout>

Above file have one button and one scroll view. Inside the scroll view, there are UI widgets like text view and image view.

There are three text views and three image views are there.

All these widgets are the children of one single Linear layout and this linear layout is the one and only child of scroll view.

So above file will generate the scrollable view layout and we will take the screen shot of this whole scroll view.

Now write down the following source lines in MainActivity.kt file.

import android.Manifest
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.Color
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.os.Environment
import android.util.Log
import android.view.View
import android.widget.Button
import android.widget.ScrollView
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.FileNotFoundException
import java.io.FileOutputStream
import java.io.IOException
import java.util.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        requestReadPermissions()

        var scrollView: ScrollView? = null
        var btn: Button? = null

        scrollView = findViewById(R.id.scroll)
        btn = findViewById(R.id.btn)

        btn.setOnClickListener(View.OnClickListener {
            bitScroll = getBitmapFromView(scrollView, scrollView.getChildAt(0).height, scrollView.getChildAt(0).width)
            saveBitmap(bitScroll)
            val intent = Intent(this@MainActivity, PreviewActivity::class.java)
            startActivity(intent)
        })

 }

    companion object {
        lateinit var bitScroll: Bitmap
    }

    //create bitmap from the ScrollView
    private fun getBitmapFromView(view: View, height: Int, width: Int): Bitmap {
        val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bitmap)
        val bgDrawable = view.background
        if (bgDrawable != null)
            bgDrawable.draw(canvas)
        else
            canvas.drawColor(Color.WHITE)
        view.draw(canvas)
        return bitmap
    }

    fun saveBitmap(bitmap: Bitmap) {

        val now = Date()
        android.text.format.DateFormat.format("yyyy-MM-dd_hh:mm:ss", now)
        val mPath = Environment.getExternalStorageDirectory().toString() + "/" + now + ".jpeg"
        val imagePath = File(mPath)

        val fos: FileOutputStream
        try {
            fos = FileOutputStream(imagePath)
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos)
            fos.flush()
            fos.close()
            Toast.makeText(applicationContext, imagePath.absolutePath + "", Toast.LENGTH_LONG).show()
            Log.e("ImageSave", "Saveimage")
        } catch (e: FileNotFoundException) {
            Log.e("GREC", e.message, e)
        } catch (e: IOException) {
            Log.e("GREC", e.message, e)
        }

    }

    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()
    }

}

More Information

Inside onCreate() method, compiler will execute the 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 asking the runtime permissions from the user.

For this purpose, compiler will use the various classes of the dexter library to simplify the whole process.

We are asking for READ and WRITE external storage permissions for this project

We can add any number of permissions in this requestReadPermissions() method as the project requirement.

First of all, see the below

   var scrollView: ScrollView? = null
        var btn: Button? = null

        scrollView = findViewById(R.id.scroll)
        btn = findViewById(R.id.btn)

        btn.setOnClickListener(View.OnClickListener {
            bitScroll = getBitmapFromView(scrollView, scrollView.getChildAt(0).height, scrollView.getChildAt(0).width)
            saveBitmap(bitScroll)
            val intent = Intent(this@MainActivity, PreviewActivity::class.java)
            startActivity(intent)
        })

Compiler will first create the objects of Scrollview and Button class and after this, it will find them using the IDs.

When the user clicks the button, compiler will take the screen shot of the scroll view.

For getting the bitmap of the screen shot, it will use getBitmapFromView() method.

Below is the source snippet for getBitmapFromView() method.

 private fun getBitmapFromView(view: View, height: Int, width: Int): Bitmap {
        val bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(bitmap)
        val bgDrawable = view.background
        if (bgDrawable != null)
            bgDrawable.draw(canvas)
        else
            canvas.drawColor(Color.WHITE)
        view.draw(canvas)
        return bitmap
    }

In this method, compiler will take the screen shot of whole scroll view and then it will create the bitmap of this screen shot.

This method will get the scroll view in it’s first parameter as the object of the View class.

It will get the height and width of the whole screen in the second and third parameter respectively.

Then it will save the bitmap using the saveBitmap() method.

After this, it will open the PreviewActivity to show case the image of the scroll view.

Step 3. Showing the Image

Make a new activity and give it a name like Preview Activity.

You need to add the following code lines in activity_preview.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              xmlns:tools="http://schemas.android.com/tools"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical"
              tools:context=".PreviewActivity">

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

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

            <Button
                    android:layout_width="match_parent"
                    android:layout_height="80dp"
                    android:layout_marginTop="10dp"
                    android:gravity="center"
                    android:text="Below is your ScreenShot"
                    android:textSize="20sp"
                    android:layout_marginBottom="20dp"/>

            <ImageView
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:src="@drawable/silver"
                    android:id="@+id/img"/>

        </LinearLayout>



    </ScrollView>
</LinearLayout>

There is also one scroll view in this layout file. Inside this scroll view, there is one button and one Image view.

Now the source snippet for PreviewActivity.kt file is as the following

import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import android.widget.ImageView

class PreviewActivity : AppCompatActivity() {

    private var imageView: ImageView? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_preview)

        imageView = findViewById(R.id.img)

        imageView!!.setImageBitmap(MainActivity.bitScroll)

    }
}

In this activity, we will see the captured image of the scroll view.

Above lines are very simple. Compiler will get the image view ID and then it will set the bitmap into the image view.

For this, we will use the bitmap which is defined in the Main activity.

So it was all the information for this example. Hope you liked it and have successfully completed it !

Download Kotlin Take Scrollview Screenshot

https://github.com/demonuts/kotlin-take-scrollview-screenshot-Programmatically-Full-Long-Activity-Page