Android Kotlin: How to change Bitmap opacity

This code demonstrates how to adjust the opacity of a Bitmap image in an Android application written in Kotlin. It utilizes a SeekBar widget to allow users to interactively control the transparency level.

The code is divided into three main parts:

  1. Activity Code (MainActivity.kt): This section handles the core functionality of the app. It retrieves references to UI elements like ImageViews, TextViews, and the SeekBar from the activity layout. Then, it loads a bitmap from the assets folder and displays it in the first ImageView. The key functionality lies in the setOpacity function, explained later. Finally, a SeekBar listener is implemented to capture user interaction and dynamically update the second ImageView with a modified version of the original bitmap having adjusted transparency based on the SeekBar position.

  2. Extension Functions: The code defines two extension functions. The first, assetsToBitmap, simplifies loading a bitmap image from the application's assets directory. The second, setOpacity, is responsible for modifying the opacity of a given Bitmap.

  3. Layout (activity_main.xml): This file defines the user interface layout of the application using ConstraintLayout. It positions the ImageViews to display the original and modified bitmaps, a TextView to indicate their purpose, a SeekBar for user input, and another TextView to provide feedback on the selected opacity level.

Summary

This code provides a user-friendly way to adjust the transparency of an image in an Android app. Users can manipulate a SeekBar to control the opacity level, with visual feedback provided through the updated image and informative text displays. The code leverages extension functions to improve readability and maintainability.


MainActivity.kt

package com.cfsuman.kotlintutorials

import android.app.Activity
import android.content.Context
import android.graphics.*
import android.os.Bundle
import android.widget.*
import java.io.IOException
import kotlin.math.roundToInt


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

        // get the widgets reference from XML layout
        val imageView = findViewById<ImageView>(R.id.imageView)
        val imageView2 = findViewById<ImageView>(R.id.imageView2)
        val textView = findViewById<TextView>(R.id.textView)
        val textView2 = findViewById<TextView>(R.id.textView2)
        val seekBar = findViewById<SeekBar>(R.id.seekBar)


        // get the bitmap from assets folder
        val bitmap = assetsToBitmap("flower103.jpg")


        bitmap?.apply {
            // show original bitmap in first image view
            imageView.setImageBitmap(this)
            textView.text = "Original Bitmap"

            seekBar.setOnSeekBarChangeListener(
                object : SeekBar.OnSeekBarChangeListener {
                override fun onProgressChanged(
                    seekBar: SeekBar?,
                    progress: Int,
                    fromUser: Boolean
                ) {
                    // show the transparent bitmap in image view
                    imageView2.setImageBitmap(setOpacity(progress))
                    textView2.text = "Bitmap Opacity $progress%"
                    textView2.append("\n0% full transparent " +
                            "100% full opaque")

                    val alpha = (progress * 2.55).roundToInt()
                    textView2.append("\nAlpha value " +
                            "$alpha (Range 0..255)")
                }

                override fun onStartTrackingTouch(seekBar: SeekBar?) {
                }

                override fun onStopTrackingTouch(seekBar: SeekBar?) {
                }
            })
        }
    }
}



// extension function to get bitmap from assets
fun Context.assetsToBitmap(fileName:String):Bitmap?{
    return try {
        val stream = assets.open(fileName)
        BitmapFactory.decodeStream(stream)
    } catch (e: IOException) {
        e.printStackTrace()
        null
    }
}



// extension function to set bitmap opacity by percent
fun Bitmap.setOpacity(opacityPercent:Int):Bitmap?{
    val bitmap = copy(Bitmap.Config.ARGB_8888,true)

    // int: set the alpha component [0..255] of the paint's color.
    // 0 is full transparent
    // 255 is full opaque
    val opacity = (opacityPercent * 2.55).roundToInt()
    val color = opacity and 0xFF shl 24

    Canvas(bitmap).drawColor(color, PorterDuff.Mode.DST_IN)
    return bitmap
}
activity_main.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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/rootLayout"
    android:background="#DCDCDC"
    android:padding="24dp">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="0dp"
        android:layout_height="225dp"
        android:layout_marginTop="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="Original Bitmap"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="@+id/imageView"
        app:layout_constraintTop_toBottomOf="@+id/imageView" />

    <ImageView
        android:id="@+id/imageView2"
        android:layout_width="0dp"
        android:layout_height="225dp"
        android:layout_marginTop="12dp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

    <SeekBar
        android:id="@+id/seekBar"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:max="100"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/imageView2" />

    <TextView
        android:id="@+id/textView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        android:text="Transparent Bitmap"
        app:layout_constraintEnd_toEndOf="@+id/imageView2"
        app:layout_constraintStart_toStartOf="@+id/imageView2"
        app:layout_constraintTop_toBottomOf="@+id/seekBar" />

</androidx.constraintlayout.widget.ConstraintLayout>
More android kotlin tutorials