简体   繁体   English

检测当前在RecyclerView中滚动到哪个项目

[英]Detect which item is currently scrolled to in RecyclerView

I'm trying to implement an autoplay feature for video items in a RecyclerView (linear vertical layout). 我正在尝试为RecyclerView(线性垂直布局)中的视频项目实现自动播放功能。 I can't figure out how to know when a certain item is currently on/off the screen so I can autoplay/pause the video. 我不知道如何知道当前何时在屏幕上打开/关闭某个项目,因此我可以自动播放/暂停视频。 If I put the code in onBindViewHolder method all videos start playing simultaniously. 如果将代码放在onBindViewHolder方法中,则所有视频将同时开始播放。 Couldn't find a solution by googling it either. 也无法通过谷歌搜索找到解决方案。 Help, please! 请帮助!

For Recyclerview you should rely on your layout manager to give you this information. 对于Recyclerview,您应该依靠布局管理器来提供此信息。

https://developer.android.com/reference/android/support/v7/widget/GridLayoutManager or https://developer.android.com/reference/android/support/v7/widget/LinearLayoutManager https://developer.android.com/reference/android/support/v7/widget/GridLayoutManagerhttps://developer.android.com/reference/android/support/v7/widget/LinearLayoutManager

Assign a layout to the RecyclerView when you assign the adapter. 分配适配器时,将布局分配给RecyclerView。 Then use it to see what is visible. 然后使用它来查看可见的内容。

在此处输入图片说明

Let me help a bit more with some Psedo Kotlin code for you to help with the player aspect. 让我通过一些Psedo Kotlin代码为您提供更多帮助,以帮助您改善播放器方面。

Let's pretend you have some object that is bound into each row that can trigger the playing and has a unique ID. 假设您有一些绑定到每一行的对象可以触发播放,并且具有唯一的ID。 Let's call that an ActiveRowPlayer for this example. 在本示例中,我们将其称为ActiveRowPlayer。

NOTE* If you are using databinding, it is simple to bind your video player playing content to a property in your model that is populating the row, but that's different story for a different post. 注意*如果使用的是数据绑定,将视频播放器的播放内容绑定到填充行的模型中的属性很简单,但这对于不同的帖子来说是不同的。

You can make an interface like: 您可以制作一个类似以下的界面:

interface IActivePlayerUpdater{
    fun onUpdateCurrentPlayer
}

You can make a helper method like: 您可以制作如下的辅助方法:

in your activity, you can implement an interface like :IActivePlayerUpdater and override the methods for it. 在您的活动中,您可以实现:IActivePlayerUpdater之类的接口,并覆盖其方法。

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

Then pass it into your adapter and just monitor your onBind method and anytime a new onBind is called that means the content has moved enough to trigger a new row item. 然后将其传递到适配器中,并仅监视onBind方法,并在每次调用新的onBind时都意味着内容已移动到足以触发新行项目的位置。

MyAdapterConstructor(IActivePlayerUpdater myCallback)

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

Keep in mind, this is just pseudo to help you on your journey. 请记住,这只是伪造的,可帮助您旅途中。 not intended to be direct copy and paste. 不打算直接复制和粘贴。

----NOTE* REQUESTED FROM COMMENT TO SUPPLY HOW TO TOUCH VIEWMODEL FROM OUTSIDE OF ADAPTER--- ---- NOTE *从评论中要求提供如何从适配器外部触摸视图模型-

@Goran, this example I had setup a long time ago to avoid notifyDataSetChanged on selection changed to toggle a checkbox for each item. @Goran,此示例是我很久以前设置的,以避免在将选择更改为每个项目切换复选框时避免notifyDataSetChanged。 I eventually moved to a better option, but you asked how do you get the viewmodel, here is a sample. 我最终转向了一个更好的选择,但是您问如何获取视图模型,这是一个示例。 rvCameraRoll was my recyclerView, I was using it to display camera media, but that is not relevant, just focus on getting the viewModel piece. rvCameraRoll是我的recyclerView,我用它来显示相机媒体,但这无关紧要,只专注于获取viewModel部分。

The only part you should care about is getting the ViewHolder, I just left the rest there in case it helps you with anything else. 您唯一需要关心的部分就是获取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);

        }

    }

OLD

leaving this for anyone using a ListView 留给任何使用ListView的人

There is a OnScrollListener for ListView ListView有一个OnScrollListener

You can override the 您可以覆盖

onScrollStateChanged(AbsListView view, int scrollState)

and the

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

this will give you the ListView item that is visible. 这将为您提供可见的ListView项。 So by using the onScroll you can detect which items are visible and determine which one to play and stop playing. 因此,通过使用onScroll,您可以检测到可见的项目并确定要播放和停止播放的项目。

if you use with recyclerview https://developer.android.com/reference/android/support/v7/widget/RecyclerView.OnScrollListener 如果您与recyclerview一起使用https://developer.android.com/reference/android/support/v7/widget/RecyclerView.OnScrollListener

The RecyclerView is only holding the items and the LayoutManager is responsible for displaying the items, so in order to get the ones that are visible to the user, assuming that you use LinearLayoutManager, you should call : ((LinearLayoutManager)recyclerView.getLayoutManager()).findFirstVisibleItemPosition(); RecyclerView仅保存项目,而LayoutManager负责显示项目,因此为了获得用户可见的项目,假设您使用LinearLayoutManager,则应调用:(((LinearLayoutManager)recyclerView.getLayoutManager() ).findFirstVisibleItemPosition(); or ((LinearLayoutManager)recyclerView.getLayoutManager()).findLastVisibleItemPosition(); 或(((LinearLayoutManager)recyclerView.getLayoutManager())。findLastVisibleItemPosition();或

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM