Epoxy - 在RecyclerView中构建复杂界面 - 8

506 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

可见性事件

自2.19.0支持

Epoxy支持在视图滚动进出屏幕的时候通知回调. 这个项定义了可见性状态.

  • 可见: 在视图至少 1 象素可见的时候触发.
  • 不可见: 在视图在屏幕上不再有象素的时候触发.
  • 聚焦: 在视图占据了视口至少一半, 或者小于一半但视图完全可见的时候触发.
  • 可见未聚焦: 在视图不再聚焦的时候触发, 比如, 视图不完全可见, 也没有占据至少一半视口.
  • 完全可见: 在整个视图在某一时候穿过了视口的时候触发.

为RecyclerView启用可见性事件

可见性变更回调必须在每一个RecyclerView通过使用EpoxyVisibilityTracker启用:

val epoxyVisibilityTracker = EpoxyVisibilityTracker()
epoxyVisibilityTracker.attach(recyclerView)

这种方式向RecyclerView添加了监听器, 监听器在每一次滚动或者布局变更的时候检查可见性变化.

Model 和视图的可见性回调不会被调用, 除非在其所在RecyclerView上手动触发.

可见性变更的回调

有 2 个接口与可见性状态进行通讯.

OnModelVisibilityStateChangedListener - 这个接口在视图的可见性状态发生变更的时候进行通知, 比如从不可见变为可见.

OnModelVisibilityChangedListener - 这是更细粒度的回调, 能够精确在告知视图在屏幕上有多少可见性.

注册回调

对于这 2 个可见性接口的回调注册, 有几种方式.

构建 Model 时

在实例化生成的 Model 并且在其上设置数据时, 可以对特定 Model 实例注册可见性监听器.

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
  }

覆盖 Model 时

如果在创建自己的EpoxyModel子类(比如使用了 ViewHolder 的 Model), 那么可以直接覆盖可见性回调以接收那种类型 Model 的全部事件.

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
  ) {

  }
}

@ModelView注解的自定义视图内部

如果在使用@ModelView注解来生成自定义视图的 Model, 那么可以在视图内部注解函数来直接接收可见性回调.

这里有 2 个注解, 各负责一种回调类型.

OnVisibilityStateChanged

OnVisibilityChanged

必须保证注解的函数拥有正确的签名, 否则的话Epoxy将会在编译期提供错误. 用法如下:

@ModelView
class MyView extends View {

@OnVisibilityStateChange
void myMethodForWatchingVisibilityState(@VisibilityState int state) {

}

@OnVisibilityStateChanged
void myMethodForWatchingVisibility(
    float percentVisibleHeight, float percentVisibleWidth,
    int visibleHeight, int visibleWidth
){

}

与EpoxyModelGroup一起使用

注意: EpoxyModelGroup内部的 Model 当前并不支持在其上注册监听器 - 其上注册的监听器不会接收任何可见性回调. 只有最顶层的组 Model 会接收到可见性回调.

如果想在EpoxyModelGroup上注册可见性回调, 那么必须使用生成的相应的子类, 由此可见性回调都会生成. 定义EpoxyModelGroup子类并添加@EpoxyModelClass注解会强制生成类 - 之后再使用这个生成类.

EpoxyModelGroup在未来可能会被修改以内置可见性处理.