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 !