Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change tint color of images which below overlay view

I have a scroll view which contains a lot of images. I want to implement a highlight zone which changes color of all views below it (only part of view which right below the zone)

enter image description here

Here are the layout, vOverlayColor is the view that I want to set overlay color.

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

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

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

            <ImageView
                android:layout_width="100dp"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/spacing_large"
                android:adjustViewBounds="true"
                android:src="@drawable/ic_delete"
                android:tint="@color/colorGreyDark"
                tools:ignore="ContentDescription" />

            <ImageView
                android:layout_width="100dp"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/spacing_large"
                android:adjustViewBounds="true"
                android:src="@drawable/ic_delete"
                android:tint="@color/colorGreyDark"
                tools:ignore="ContentDescription" />

            <ImageView
                android:layout_width="100dp"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/spacing_large"
                android:adjustViewBounds="true"
                android:src="@drawable/ic_delete"
                android:tint="@color/colorGreyDark"
                tools:ignore="ContentDescription" />

            <ImageView
                android:layout_width="100dp"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/spacing_large"
                android:adjustViewBounds="true"
                android:src="@drawable/ic_delete"
                android:tint="@color/colorGreyDark"
                tools:ignore="ContentDescription" />

            <ImageView
                android:layout_width="100dp"
                android:layout_height="wrap_content"
                android:layout_margin="@dimen/spacing_large"
                android:adjustViewBounds="true"
                android:src="@drawable/ic_delete"
                android:tint="@color/colorGreyDark"
                tools:ignore="ContentDescription" />
        </LinearLayout>
    </ScrollView>

    <View
        android:id="@+id/vOverlayColor"
        android:layout_width="match_parent"
        android:layout_height="120dp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

Do you have any suggestion?

like image 696
Duy Khanh Nguyen Avatar asked Oct 15 '22 09:10

Duy Khanh Nguyen


1 Answers

Here measureAndSetup function loops over all views inside Linear layout (which is the direct child of scrollview) and finds the intersecting region with the overlay view and applies the changeColor function appropriately. The change color function gets the bitmap inside imageview, colors it to blue if the pixel is inside the intersecting region (a constant is used as the imageview dimension and bitmap dimension queried at runtime are different), rest areas are colored black.

The views completely out of overlay area are tinted black.

Have a look at my code and give a try

import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.drawable.BitmapDrawable
import android.os.Bundle
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.forEachIndexed
import kotlinx.android.synthetic.main.activity_main.*


class MainActivity : AppCompatActivity() {


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


    sv.viewTreeObserver.addOnGlobalLayoutListener {
        measureAndSetup()
    }

    sv.getViewTreeObserver().addOnScrollChangedListener {
        measureAndSetup()
    }


}

private fun measureAndSetup() {
    val top = sv.scrollY + vOverlayColor.top
    val bottom = top + vOverlayColor.height
    ll01.forEachIndexed { index, view ->
        val iv = view as ImageView
        if (view.bottom >= top && view.top <= top) {
            if (view.bottom <= bottom) {
                //starts on top and ends inside overlay
                changeColor(iv, top - view.top, view.height)
            } else {
                // starts on top and ends below
                changeColor(iv, top - view.top, top - view.top + 
 vOverlayColor.height)
            }
        } else if (view.top >= top && view.bottom <= bottom) {
            //starts inside overlay and ends inside
            changeColor(iv, 0, view.height)

        } else if (view.top <= bottom && view.top >= top && view.bottom > 
 bottom) {
            //starts inside and ends outside
            changeColor(iv, 0, view.height - (view.bottom - bottom))

        } else {
            iv.setImageDrawable(iv.drawable.apply {
                setTint(Color.BLACK)
            })
        }

    }
}


fun changeColor(view: ImageView, startHt: Int, endHt: Int) {
    val bitmapDrawable = view.getDrawable() as BitmapDrawable
    val bitmap = bitmapDrawable.bitmap
    val bmCopy = Bitmap.createBitmap(bitmap.getWidth(), 
 bitmap.getHeight(), bitmap.getConfig())

    val const = view.height / bitmap.height
    for (i in 0 until bitmap.getWidth()) {
        for (j in 0 until bitmap.getHeight()) {
            if (j * const > startHt && j * const < endHt) {
                val p = bitmap.getPixel(i, j)
                bmCopy.setPixel(i, j, Color.argb(Color.alpha(p), 0, 0, 
  255))
            } else {
                val p = bitmap.getPixel(i, j)
                bmCopy.setPixel(i, j, Color.argb(Color.alpha(p), 0, 0, 0))
            }
        }
    }
    view.setImageBitmap(bmCopy)

}


}

And here is my 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"
tools:context=".MainActivity">


<ScrollView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/sv"
    android:fillViewport="true">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:id="@+id/ll01">

        <ImageView
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:id="@+id/iv"
            android:layout_margin="20dp"
            android:adjustViewBounds="true"
            android:src="@drawable/ic_delete"
            tools:ignore="ContentDescription" />

        <ImageView
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:layout_margin="20dp"

            android:src="@drawable/ic_delete"
            tools:ignore="ContentDescription" />

        <ImageView
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:src="@drawable/ic_delete"
            android:layout_margin="20dp"

            tools:ignore="ContentDescription" />

        <ImageView
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:layout_margin="20dp"

            android:src="@drawable/ic_delete"
            tools:ignore="ContentDescription" />

        <ImageView
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:src="@drawable/ic_delete"
            android:layout_margin="20dp"

            tools:ignore="ContentDescription" />

        <ImageView
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:src="@drawable/ic_delete"
            android:layout_margin="20dp"

            tools:ignore="ContentDescription" />

        <ImageView
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:src="@drawable/ic_delete"
            android:layout_margin="20dp"

            tools:ignore="ContentDescription" />

        <ImageView
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:src="@drawable/ic_delete"
            android:layout_margin="20dp"

            tools:ignore="ContentDescription" />

        <ImageView
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:src="@drawable/ic_delete"
            android:layout_margin="20dp"

            tools:ignore="ContentDescription" />

        <ImageView
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:src="@drawable/ic_delete"
            android:layout_margin="20dp"

            tools:ignore="ContentDescription" />

        <ImageView
            android:layout_width="100dp"
            android:layout_height="wrap_content"
            android:adjustViewBounds="true"
            android:src="@drawable/ic_delete"
            android:layout_margin="20dp"

            tools:ignore="ContentDescription" />
    </LinearLayout>
</ScrollView>

<View
    android:id="@+id/vOverlayColor"
    android:layout_width="match_parent"
    android:layout_height="180dp"
    android:foreground="@color/colorPrimaryDark"
    android:alpha="0.2"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"/>


</androidx.constraintlayout.widget.ConstraintLayout>
like image 83
Ramees Thattarath Avatar answered Oct 20 '22 17:10

Ramees Thattarath