-
Notifications
You must be signed in to change notification settings - Fork 727
Visibility Events
Since 2.19.0
Epoxy supports notifying callbacks when views scroll on and off of the screen. Visibility state is defined with these terms.
- Visible: Triggered when at least one pixel of the view is visible.
- Invisible: Triggered when the view no longer has any pixels on the screen.
- Focused: Event: Triggered when either the view occupies at least half of the viewport, or, if the view is smaller than half the viewport, when it is fully visible.
- Unfocused Visible: Triggered when the view is no longer focused, i.e. it is not fully visible and does not occupy at least half the viewport.
- Full Impression Visible: Triggered when the entire view has passed through the viewport at some point.
Visibility change callbacks must be enabled on a per RecyclerView basis by using the EpoxyVisibilityTracker
val epoxyVisibilityTracker = EpoxyVisibilityTracker()
epoxyVisibilityTracker.attach(recyclerView)
This adds listeners to the RecyclerView that check for visibility changes on every scroll or layout change.
Your model and view visibility callbacks will not be called unless you do this for the RecyclerView they are shown in.
There are two interfaces that communicate visibility status.
OnModelVisibilityStateChangedListener - This notifies you when the visibility state of the view changes, such as going from invisible to visible.
OnModelVisibilityChangedListener - This is a more granular callback that tells you exactly how much of the view is visible on screen.
There are several ways to register callbacks for the two visibility interfaces.
When you instantiate a generated model and set your data on it you can register visibility listeners for that specific model instance
new MyModel_()
.id("my id")
.onVisibilityStateChanged { model, view, visibilityState ->
// Do something with the new visibility state
}
.onVisibilityChanged { model, view, percentVisibleHeight, percentVisibleWidth, visibleHeight, visibleWidth ,view ->
// Do something with the visibility information
}
If you are creating your own EpoxyModel subclass (such as a model that uses a viewholder) then you can override the visibility callbacks directly to get notified of all events for models of that type.
class MyModel extends EpoxyModelWithHolder<Holder> {
... // Set up your model as usual
// Override these visibility callbacks as needed
public void onVisibilityStateChanged(@Visibility int visibilityState, @NonNull T view) {
}
public void onVisibilityChanged(
@FloatRange(from = 0.0f, to = 100.0f) float percentVisibleHeight,
@FloatRange(from = 0.0f, to = 100.0f) float percentVisibleWidth,
@Px int visibleHeight,
@Px int visibleWidth,
@NonNull T view
) {
}
}
If you are using the @ModelView
annotation to generate models from custom views then you can annotate methods within your view to receive visibility callbacks directly in the view.
There are two annotations, one for each callback type.
You must make sure that your annotated methods have the correct signature, otherwise Epoxy will provide an error at compile time. Usage looks like:
@ModelView
class MyView extends View {
@OnVisibilityStateChange
void myMethodForWatchingVisibilityState(@VisibilityState int state) {
}
@OnVisibilityStateChanged
void myMethodForWatchingVisibility(
float percentVisibleHeight, float percentVisibleWidth,
int visibleHeight, int visibleWidth
){
}
Note that models within an EpoxyModelGroup
do not currently support registering visibility listeners on them - they will not get any visibility callbacks. Only the top level group model will receive visibility callbacks.
If you do want to register visibility callbacks on EpoxyModelGroup
then you must use a generated subclass of it, so that the visibility callbacks are generated. Make a subclass of EpoxyModelGroup
and add the @EpoxyModelClass
annotation to it to force a generated class to be created - then use the resulting generated class.
EpoxyModelGroup could be modified in the future to have visibility handling built in - pull requests are welcome!