ImageFilterView is a An ImageView that can display, combine and filter images, to handle various common filtering operations. You can set saturation, contrast, warmth and some othters (refer to the document) in layout XML, or change it at run-time.
VIDEO
ImageFilterView was added in ConstraintLayout 2.0, so make sure dependencies of implementation 'androidx.constraintlayout:constraintlayout:2.0.0' or higher is include in your build.grade(Module:) file.
build.grade(Module:)
dependencies {
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
}
Layout 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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="20dp"
tools:context=".MainActivity">
<LinearLayout
android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toTopOf="@id/imagefilterview"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="ImageFilterView Example (Kotlin)"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Android-er.blogspot.com" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:mipmap/sym_def_app_icon"/>
</LinearLayout>
<androidx.constraintlayout.utils.widget.ImageFilterView
android:id="@+id/imagefilterview"
android:src="@android:mipmap/sym_def_app_icon"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/panel"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/header"
app:saturation="1.0"
app:contrast="1.0"
app:brightness="1.0"/>
<LinearLayout
android:id="@+id/panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/imagefilterview">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Saturation"/>
<TextView
android:id="@+id/sat"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<SeekBar
android:id="@+id/seekBarSat"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="50"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Contrast"/>
<TextView
android:id="@+id/cont"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<SeekBar
android:id="@+id/seekBarCont"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="50"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Warmth"/>
<TextView
android:id="@+id/warm"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<SeekBar
android:id="@+id/seekBarWarm"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="50"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Kotlin code:
package com.blogspot.android_er.eximgfilterview2
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.SeekBar
import android.widget.TextView
import androidx.constraintlayout.utils.widget.ImageFilterView
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val MyImageFilterView =
findViewById<ImageFilterView>(R.id.imagefilterview)
val MySeekBarSat = findViewById<SeekBar>(R.id.seekBarSat)
val MyTextViewSat = findViewById<TextView>(R.id.sat)
val MySeekBarCont = findViewById<SeekBar>(R.id.seekBarCont)
val MyTextViewCont = findViewById<TextView>(R.id.cont)
val MySeekBarWarm = findViewById<SeekBar>(R.id.seekBarWarm)
val MyTextViewWarm = findViewById<TextView>(R.id.warm)
//Get the first-run setting of saturation, contrast and warmth
MyTextViewSat.text= MyImageFilterView.saturation.toString()
MyTextViewCont.text= MyImageFilterView.contrast.toString()
MyTextViewWarm.text= MyImageFilterView.warmth.toString()
MySeekBarSat.setOnSeekBarChangeListener(
object : SeekBar.OnSeekBarChangeListener{
override fun onProgressChanged(seekBar: SeekBar?,
progress: Int, fromUser: Boolean) {
//update saturation
MyImageFilterView.saturation = (progress / 100.0f) * 2
//read back the saturation
MyTextViewSat.text= MyImageFilterView.saturation.toString()
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
override fun onStopTrackingTouch(seekBar: SeekBar?) {}
})
MySeekBarCont.setOnSeekBarChangeListener(
object : SeekBar.OnSeekBarChangeListener{
override fun onProgressChanged(seekBar: SeekBar?,
progress: Int, fromUser: Boolean) {
MyImageFilterView.contrast = (progress / 100.0f) * 2
MyTextViewCont.text= MyImageFilterView.contrast.toString()
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
override fun onStopTrackingTouch(seekBar: SeekBar?) {}
})
MySeekBarWarm.setOnSeekBarChangeListener(
object : SeekBar.OnSeekBarChangeListener{
override fun onProgressChanged(seekBar: SeekBar?,
progress: Int, fromUser: Boolean) {
MyImageFilterView.warmth = (progress / 100.0f) * 2
MyTextViewWarm.text= MyImageFilterView.warmth.toString()
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
override fun onStopTrackingTouch(seekBar: SeekBar?) {}
})
}
}
Then add the feature to change Crossfade, also show how overlay setting affect the crossfade result.
VIDEO
Layout 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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="20dp"
tools:context=".MainActivity">
<LinearLayout
android:id="@+id/header"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toTopOf="@id/imagefilterview"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="ImageFilterView Example (Kotlin)"
android:textStyle="bold" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Android-er.blogspot.com" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@android:mipmap/sym_def_app_icon"/>
</LinearLayout>
<androidx.constraintlayout.utils.widget.ImageFilterView
android:id="@+id/imagefilterview"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/panel"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/header"
android:src="@android:mipmap/sym_def_app_icon"
app:altSrc="@android:drawable/btn_star_big_on"
app:overlay="false"
app:crossfade="0.0"
app:saturation="1.0"
app:contrast="1.0"
app:warmth="1.0"
/>
<LinearLayout
android:id="@+id/panel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/imagefilterview">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Crossfade"/>
<TextView
android:id="@+id/crossfade"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<SeekBar
android:id="@+id/seekBarCrossfade"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="0"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Saturation"/>
<TextView
android:id="@+id/sat"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<SeekBar
android:id="@+id/seekBarSat"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="50"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Contrast"/>
<TextView
android:id="@+id/cont"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<SeekBar
android:id="@+id/seekBarCont"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="50"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Warmth"/>
<TextView
android:id="@+id/warm"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<SeekBar
android:id="@+id/seekBarWarm"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:max="100"
android:progress="50"/>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Kotlin code:
package com.blogspot.android_er.eximgfilterview2
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.SeekBar
import android.widget.TextView
import androidx.constraintlayout.utils.widget.ImageFilterView
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val MyImageFilterView =
findViewById<ImageFilterView>(R.id.imagefilterview)
val MySeekBarCrossfade = findViewById<SeekBar>(R.id.seekBarCrossfade)
val MyTextViewCrossfade = findViewById<TextView>(R.id.crossfade)
val MySeekBarSat = findViewById<SeekBar>(R.id.seekBarSat)
val MyTextViewSat = findViewById<TextView>(R.id.sat)
val MySeekBarCont = findViewById<SeekBar>(R.id.seekBarCont)
val MyTextViewCont = findViewById<TextView>(R.id.cont)
val MySeekBarWarm = findViewById<SeekBar>(R.id.seekBarWarm)
val MyTextViewWarm = findViewById<TextView>(R.id.warm)
//Get the first-run setting of crossfade, saturation, contrast and warmth
MyTextViewCrossfade.text= MyImageFilterView.crossfade.toString()
MyTextViewSat.text= MyImageFilterView.saturation.toString()
MyTextViewCont.text= MyImageFilterView.contrast.toString()
MyTextViewWarm.text= MyImageFilterView.warmth.toString()
MySeekBarCrossfade.setOnSeekBarChangeListener(
object : SeekBar.OnSeekBarChangeListener{
override fun onProgressChanged(seekBar: SeekBar?,
progress: Int, fromUser: Boolean) {
//update saturation
MyImageFilterView.crossfade = (progress / 100.0f)
//read back the saturation
MyTextViewCrossfade.text= MyImageFilterView.crossfade.toString()
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
override fun onStopTrackingTouch(seekBar: SeekBar?) {}
})
MySeekBarSat.setOnSeekBarChangeListener(
object : SeekBar.OnSeekBarChangeListener{
override fun onProgressChanged(seekBar: SeekBar?,
progress: Int, fromUser: Boolean) {
//update saturation
MyImageFilterView.saturation = (progress / 100.0f) * 2
//read back the saturation
MyTextViewSat.text= MyImageFilterView.saturation.toString()
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
override fun onStopTrackingTouch(seekBar: SeekBar?) {}
})
MySeekBarCont.setOnSeekBarChangeListener(
object : SeekBar.OnSeekBarChangeListener{
override fun onProgressChanged(seekBar: SeekBar?,
progress: Int, fromUser: Boolean) {
MyImageFilterView.contrast = (progress / 100.0f) * 2
MyTextViewCont.text= MyImageFilterView.contrast.toString()
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
override fun onStopTrackingTouch(seekBar: SeekBar?) {}
})
MySeekBarWarm.setOnSeekBarChangeListener(
object : SeekBar.OnSeekBarChangeListener{
override fun onProgressChanged(seekBar: SeekBar?,
progress: Int, fromUser: Boolean) {
MyImageFilterView.warmth = (progress / 100.0f) * 2
MyTextViewWarm.text= MyImageFilterView.warmth.toString()
}
override fun onStartTrackingTouch(seekBar: SeekBar?) {}
override fun onStopTrackingTouch(seekBar: SeekBar?) {}
})
}
}