Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add aggregate visibility state changed callback #1385

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.airbnb.epoxy

/**
* The complete [VisibilityState]s for a single update.
*/
interface AggregateVisibilityState {
val partiallyVisible: Boolean
val fullyVisible: Boolean
val visible: Boolean
val focusedVisible: Boolean
}
10 changes: 10 additions & 0 deletions epoxy-adapter/src/main/java/com/airbnb/epoxy/EpoxyModel.java
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,16 @@ public void unbind(@NonNull T view) {
public void onVisibilityStateChanged(@Visibility int visibilityState, @NonNull T view) {
}

/**
* The aggregate {@link com.airbnb.epoxy.VisibilityState}s for this model that were previously
* sent to {@link #onVisibilityStateChanged}.
*/
public void onAggregateVisibilityStateChanged(
@NonNull AggregateVisibilityState visibilityState,
@NonNull T view
) {
}

/**
* TODO link to the wiki
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,14 @@ public void visibilityStateChanged(@Visibility int visibilityState) {
epoxyModel.onVisibilityStateChanged(visibilityState, objectToBind());
}

public void aggregateVisibilityChanged(
@NonNull AggregateVisibilityState aggregateVisibilityState
) {
assertBound();
// noinspection unchecked
epoxyModel.onAggregateVisibilityStateChanged(aggregateVisibilityState, objectToBind());
}

public void visibilityChanged(
@FloatRange(from = 0.0f, to = 100.0f) float percentVisibleHeight,
@FloatRange(from = 0.0f, to = 100.0f) float percentVisibleWidth,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import androidx.recyclerview.widget.RecyclerView
* only.
*/
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
class EpoxyVisibilityItem(adapterPosition: Int? = null) {
class EpoxyVisibilityItem(adapterPosition: Int? = null) : AggregateVisibilityState {

private val localVisibleRect = Rect()

Expand All @@ -44,10 +44,14 @@ class EpoxyVisibilityItem(adapterPosition: Int? = null) {

@Px
private var viewportWidth = 0
private var partiallyVisible = false
private var fullyVisible = false
private var visible = false
private var focusedVisible = false
override var partiallyVisible = false
private set
override var fullyVisible = false
private set
override var visible = false
private set
override var focusedVisible = false
private set
private var viewVisibility = View.GONE

/** Store last value for de-duping */
Expand Down Expand Up @@ -142,6 +146,10 @@ class EpoxyVisibilityItem(adapterPosition: Int? = null) {
}
}

fun handleAggregateVisibleState(epoxyHolder: EpoxyViewHolder) {
epoxyHolder.aggregateVisibilityChanged(this)
}

fun handleChanged(epoxyHolder: EpoxyViewHolder, visibilityChangedEnabled: Boolean): Boolean {
var changed = false
if (visibleHeight != lastVisibleHeightNotified || visibleWidth != lastVisibleWidthNotified || viewVisibility != lastVisibilityNotified) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ open class EpoxyVisibilityTracker {
}
vi.handleFocus(epoxyHolder, detachEvent)
vi.handleFullImpressionVisible(epoxyHolder, detachEvent)
vi.handleAggregateVisibleState(epoxyHolder)
changed = vi.handleChanged(epoxyHolder, onChangedEnabled)
}
return changed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,16 @@ class EpoxyVisibilityTrackerTest {
helper.fullImpression = state == FULL_IMPRESSION_VISIBLE
}
}

override fun onAggregateVisibilityStateChanged(
visibilityState: AggregateVisibilityState,
view: View
) {
helper.aggregateVisibilityState.visible = visibilityState.visible
helper.aggregateVisibilityState.focusedVisible = visibilityState.focusedVisible
helper.aggregateVisibilityState.fullyVisible = visibilityState.fullyVisible
helper.aggregateVisibilityState.partiallyVisible = visibilityState.partiallyVisible
}
}

/**
Expand All @@ -976,6 +986,8 @@ class EpoxyVisibilityTrackerTest {
var partialImpression = false
var fullImpression = false

val aggregateVisibilityState = MutableAggregateVisibilityState()

fun assert(
id: Int? = null,
visibleHeight: Int? = null,
Expand Down Expand Up @@ -1032,20 +1044,23 @@ class EpoxyVisibilityTrackerTest {
it,
this.visible
)
Assert.assertEquals(it, aggregateVisibilityState.visible)
}
partialImpression?.let {
Assert.assertEquals(
"partialImpression expected $it got ${this.partialImpression}",
it,
this.partialImpression
)
Assert.assertEquals(it, aggregateVisibilityState.partiallyVisible)
}
fullImpression?.let {
Assert.assertEquals(
"fullImpression expected $it got ${this.fullImpression}",
it,
this.fullImpression
)
Assert.assertEquals(it, aggregateVisibilityState.fullyVisible)
}
visitedStates?.let { assertVisited(it) }
}
Expand All @@ -1070,6 +1085,13 @@ class EpoxyVisibilityTrackerTest {
}
}
}

class MutableAggregateVisibilityState : AggregateVisibilityState {
override var partiallyVisible: Boolean = false
override var fullyVisible: Boolean = false
override var visible: Boolean = false
override var focusedVisible: Boolean = false
}
}
}

Expand Down