Skip to content

Instantly share code, notes, and snippets.

@dmersiyanov
Created April 28, 2022 10:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dmersiyanov/3b21437542cd6c75e741d34a49d62d12 to your computer and use it in GitHub Desktop.
Save dmersiyanov/3b21437542cd6c75e741d34a49d62d12 to your computer and use it in GitHub Desktop.
PercentVisibleCardView
import android.content.Context
import android.util.AttributeSet
import android.view.ViewTreeObserver
import androidx.cardview.widget.CardView
import ru.dpd.core.extension.getViewVisibilityPercent
class PercentVisibleCardView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null
) : CardView(context, attrs) {
var visibilityCallback: () -> Unit = {}
private var shouldNotify = true
private val scrollListener = ViewTreeObserver.OnScrollChangedListener {
val visibilityPercent = getViewVisibilityPercent()
if (shouldNotify && visibilityPercent > VISIBILITY_THRESHOLD) {
visibilityCallback.invoke()
shouldNotify = false
} else if (visibilityPercent < VISIBILITY_THRESHOLD) {
shouldNotify = true
}
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
viewTreeObserver.addOnScrollChangedListener(scrollListener)
}
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
viewTreeObserver.removeOnScrollChangedListener(scrollListener)
}
private companion object {
const val VISIBILITY_THRESHOLD = 0.7
}
}
/**
* 1f == 100%
*/
fun View.getViewVisibilityPercent(): Float {
val viewArea = width * height.toFloat()
val currentVisibleArea = Rect()
.takeIf { this.isShown }
?.takeIf(this::getGlobalVisibleRect)
?.let { it.height() * it.width() }
?.toFloat()
?: 0f
return when (viewArea) {
0f -> 0f
else -> currentVisibleArea / viewArea
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment