V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
john6lq
V2EX  ›  Android

RecyclerView 有办法优雅实现列表动画吗?

  •  
  •   john6lq · 2021-01-03 21:15:44 +08:00 via iPhone · 9339 次点击
    这是一个创建于 1423 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目前是在 onBindViewHolder 中做的。 目标需求是

    1. 页面初始化的时候不执行动画,后续滑动列表显示 item 的时候相应 item 执行动画。
    2. notifyDatasetChanges 的时候不执行动画
    13 条回复    2023-05-20 11:05:14 +08:00
    chenjiajia9411
        1
    chenjiajia9411  
       2021-01-04 09:42:51 +08:00
    john6lq
        2
    john6lq  
    OP
       2021-01-04 11:01:41 +08:00   ❤️ 1
    @chenjiajia9411 这个看过了,`itemAnimator`是`item`发生改变时才会触发,比如`add`、`remove`、`move`、`change`这些。我看了几天源码安卓上没有合适的方法做这个需求。

    但是,如果摸透了`RecyclerView`,不知道可不可以魔改 `itemAnimator`,添加一种状态来实现。
    chenjiajia9411
        3
    chenjiajia9411  
       2021-01-04 11:23:46 +08:00
    @john6lq #2 ItemAnimator 本来就不会响应 notifyDatasetChanged,因为它以单个 Item 为基本单位,在调用 notifyDatasetChanged 的时候默认都是对原有数据做了非常大的改动,无法计算有多少 Item 需要有动画,所以它会直接刷新整个 RecyclerView,ItemAnimator 根本不会被执行。
    关于你的第一个需求,可以先调用你的 RecyclerView 的 LayoutManager 的 findLastCompletelyVisibleItemPosition()或者 findLastVisibleItemPosition()方法获取界面上最后一个可见的 Item 的位置,然后直接调用 ItemAnimator 的 dispatchAnimationFinished(ViewHolder)并传入不需要动画的 ViewHolder 来取消动画。
    hstan
        4
    hstan  
       2021-01-04 14:43:35 +08:00
    MotionLayout 看看能不能满足你的需求
    pdog18
        5
    pdog18  
       2021-01-04 23:27:53 +08:00
    如果你 notifyDatasetChanged 时触发了 itemAnimator 产生动画,那么说明你在 Adapter 通过 getItem 实现了 stableId
    john6lq
        6
    john6lq  
    OP
       2021-01-05 00:10:13 +08:00 via iPhone
    @chenjiajia9411 item 进入时让这个 item 的 view 执行动画,你确定 ItemAnimator 可以做到?这个类是用于 item 数据发生改变时执行动画的。
    chenjiajia9411
        7
    chenjiajia9411  
       2021-01-05 09:38:26 +08:00
    @john6lq #6 你不信的话可以手动调用 notifyItemInserted 看看有没有效果啊,RecyclerView 默认有一个 DefaultItemAnimator ( https://developer.android.com/reference/androidx/recyclerview/widget/DefaultItemAnimator )所以能直接看到效果的。
    注意一定要是真正的向原始 list 插入一个 item 而不是把 list 整个替换之后再调用,使用 SortedList ( https://developer.android.com/reference/androidx/recyclerview/widget/SortedList )或者 AsyncListDiffer ( https://developer.android.com/reference/androidx/recyclerview/widget/AsyncListDiffer )可能是更好的选择。
    john6lq
        8
    john6lq  
    OP
       2021-01-05 11:19:50 +08:00
    @chenjiajia9411 你误会了,需求上“item 显示时”不是新增一条数据,而是这个 item 从不可见变为可见。“itemAnimator”只是在数据发生改变时提供动画。要不我提什么“onBindViewHolder”?
    q197
        9
    q197  
       2021-01-05 11:22:12 +08:00
    brvah 库
    chenjiajia9411
        10
    chenjiajia9411  
       2021-01-05 11:30:16 +08:00
    @john6lq #8 我误会了,从不可见变为可见这种状态改变可以用 notifyItemChanged,然后在 SimpleItemAnimator 的 animateChange 里做你需要的动画。
    john6lq
        11
    john6lq  
    OP
       2021-01-05 12:39:44 +08:00
    @q197 看了一下,这个库的动画是在 onViewAttachedToWindow 内执行的,这里可以看见
    https://github.com/CymChad/BaseRecyclerViewAdapterHelper/blob/master/library/src/main/java/com/chad/library/adapter/base/BaseQuickAdapter.kt

    这和在 onBindViewHolder 内执行没啥区别。另外这库其实就是个辅助类,花里胡哨的,kotlin 后用 RecyclerView 其实没必要搞这么复杂了。
    dengxuejiu
        12
    dengxuejiu  
       2023-05-19 21:17:01 +08:00
    遇到了同样的问题,请问有解决方案吗,我的需求是实现 iOS 的通知中心的滑动效果
    john6lq
        13
    john6lq  
    OP
       2023-05-20 11:05:14 +08:00
    @dengxuejiu iOS 15 用 [[Cask 3]],这个插件支持自定义列表动画
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3185 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 37ms · UTC 13:14 · PVG 21:14 · LAX 05:14 · JFK 08:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.