Detect when the specific view is shown / unshown in ScrollView

nichiyoshi
1 min readMar 29, 2020

Imagine you have a ScrollView and required to send an impression log of the specific item in the ScrollView.

How to achieve it?

The sample below demonstrates that when the visibility of “4th component” is toggled, toast that: when shown toast Text Four SHOWN!!!, and hidden toast Text Four HIDDEN!!! (This ScrollView has four TextViews)

Use getChildVisibleRect

One solution is to use getChildVisibleRect. The source code of this method is here.

First, detect when the textFourView is visible or not while scrolling.

val scrollBounds = Rect()
val point = Point()
scrollView.apply {

setOnScrollChangeListener { _, _, _, _, _ ->
// set the rect of ScrollView to scrollBounds
getHitRect(scrollBounds)
// detect if the textFour view is visible within the rect of ScrollView
val isVisible = getChildVisibleRect(textFourView, scrollBounds, point)
viewModel.toggleIsVisible(isVisible)
}}

Second, observe when the visibility is changed.

class MainViewModel: ViewModel() {

private var previousVisibility = false

private val visibilityChangedMutable = MutableLiveData<Boolean>()
val visibilityChanged: LiveData<Boolean> get() = visibilityChangedMutable.distinctUntilChanged()

fun toggleIsVisible(isVisible: Boolean) {
if(previousVisibility!= isVisible) {
visibilityChangedMutable.postValue(isVisible)
}
previousVisibility = isVisible
}

}
class MainActivity: AppCompatActivity { viewModel.visibilityChanged.observe(this) {
if(it) {
Toast.makeText(this, "Text Four SHOWN!!", Toast.LENGTH_SHORT).show()
} else {
Toast.makeText(this, "Text Four HIDDEN!!", Toast.LENGTH_SHORT).show()
}
}
}

GitHub code is here.

--

--