【问题标题】:Detect which item is currently scrolled to in RecyclerView在 RecyclerView 中检测当前滚动到哪个项目
【发布时间】:2018-10-02 12:58:47
【问题描述】:

我正在尝试为 RecyclerView(线性垂直布局)中的视频项目实现自动播放功能。我不知道如何知道某个项目当前何时打开/关闭屏幕,因此我可以自动播放/暂停视频。如果我将代码放在 onBindViewHolder 方法中,所有视频都会同时开始播放。谷歌搜索也找不到解决方案。请帮忙!

【问题讨论】:

    标签: android android-recyclerview


    【解决方案1】:

    对于 Recyclerview,您应该依靠您的布局管理器为您提供此信息。

    https://developer.android.com/reference/android/support/v7/widget/GridLayoutManager 或者 https://developer.android.com/reference/android/support/v7/widget/LinearLayoutManager

    在分配适配器时为 RecyclerView 分配一个布局。然后用它来查看可见的内容。

    让我为您提供一些 Psedo Kotlin 代码的更多帮助,以帮助您解决播放器方面的问题。

    假设您有一些对象绑定到可以触发播放并具有唯一 ID 的每一行。在本例中,我们称其为 ActiveRowPlayer。

    注意* 如果您使用数据绑定,将播放内容的视频播放器绑定到填充行的模型中的属性很简单,但对于不同的帖子,情况就不同了。

    您可以制作如下界面:

    interface IActivePlayerUpdater{
        fun onUpdateCurrentPlayer
    }
    

    您可以创建一个辅助方法,例如:

    在您的活动中,您可以实现类似 :IActivePlayerUpdater 的接口并覆盖它的方法。

    override fun onUpdateCurrentPlayer(){
        var activeRowPlayer = recyclerView.layoutManager.findFirstCompletelyVisibleItemPosition()
        if(activeRowplayer.someID != currentRowPlayer.someID){
            currentRowPlayer.stopPlaying
            currentRowPlayer = activeRowPlayer
            activeRowPlayer.startPlaying
        }
    }
    

    然后将其传递到您的适配器并仅监视您的 onBind 方法,并且每当调用新的 onBind 时,这意味着内容已移动到足以触发新的行项目。

    MyAdapterConstructor(IActivePlayerUpdater myCallback)
    
    fun recyclerView.onBindMethod(stuffThatComesHere){
        //do normal stuff
        myCallback.onUpdateCurrentPlayer()
    }
    

    请记住,这只是为了在您的旅程中为您提供帮助。不打算直接复制和粘贴。

    ----注释* 要求提供如何从适配器外部触摸视图模型---

    @Goran,我很久以前就设置了这个例子来避免 选择时的 notifyDataSetChanged 已更改为切换复选框 每一个项目。我最终转向了一个更好的选择,但你问怎么做 你得到了视图模型,这是一个示例。 rvCameraRoll 是我的 recyclerView,我用它来显示相机媒体,但那不是 相关,只需专注于获取 viewModel 部分。

    您应该关心的唯一部分是获取 ViewHolder,我只是将其余部分留在那里,以防它对您有任何帮助。

         int count = rvCameraRoll.getChildCount();
        for (int i = 0; i < count; i++) {
            MediaModelGridAdapter.ViewHolder childRow = (MediaModelGridAdapter.ViewHolder)rvCameraRoll.getChildViewHolder(rvCameraRoll.getChildAt(i));
            if(isVisible) {
                childRow.imgCellSelected.setVisibility(View.VISIBLE);
                if(getMediaModelList().get(i).getIsSelected()){
                    childRow.imgCellSelected.setBackgroundResource(R.drawable.ic_ap_selected_on);
                }
    
            }else{
                //check that exists, because after fresh delete list may be short while updating cells
                if(getMediaModelList().size() > i) {
                    getMediaModelList().get(i).setIsSelected(false);
                }
                childRow.imgCellSelected.setBackgroundResource(R.drawable.ic_ap_selected_off);
                childRow.imgCellSelected.setVisibility(View.GONE);
    
            }
    
        }
    

    留给任何使用 ListView 的人

    ListView 有一个 OnScrollListener

    你可以覆盖

    onScrollStateChanged(AbsListView view, int scrollState)

    onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)

    这将为您提供可见的 ListView 项目。因此,通过使用 onScroll,您可以检测哪些项目是可见的,并确定要播放和停止播放的项目。

    如果你使用 recyclerview https://developer.android.com/reference/android/support/v7/widget/RecyclerView.OnScrollListener

    【讨论】:

    • 没有区别。 @GoranKovač
    • 不过,这些回调并没有给我任何关于可见项目的信息,只有滚动量(dx,dy)和滚动状态......这对我有什么帮助?
    • 抱歉@GoranKovač 没有意识到 Recyclerview 使用的界面会有所不同,感谢您指出这一点。我为您更新了答案,为您提供了更好的解决方案。
    • 谢谢,就是这样,它给了我一个可见的项目......但我仍然不明白如何在项目完全可见时获得回调并让项目的对应持有人播放视频在那个回调中
    • @GoranKovač 您的问题是要知道某个项目何时在屏幕上或屏幕外。我已经为你提供了这个答案。现在您正在询问其他问题。如果您想知道如何开始播放视频或停止播放行项目,请提出一个新问题。但是,您拥有所需的一切。 onScroll 会告诉你状态已经改变,onBindView 也会告诉你新项目正在进入视图准备。每次绑定新视图时,您始终可以调用我提供给您的第一个可见项目方法,并确定播放或暂停哪个。您必须跟踪您的播放项目才能停止
    【解决方案2】:

    RecyclerView 只保存项目,而 LayoutManager 负责显示项目,因此为了获取用户可见的项目,假设您使用 LinearLayoutManager,您应该调用: ((LinearLayoutManager)recyclerView.getLayoutManager()).findFirstVisibleItemPosition(); 或者 ((LinearLayoutManager)recyclerView.getLayoutManager()).findLastVisibleItemPosition();

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多