在回收站视图中查找视图是不是在屏幕上

Posted

技术标签:

【中文标题】在回收站视图中查找视图是不是在屏幕上【英文标题】:Find if a view is on screen in a recyclerview在回收站视图中查找视图是否在屏幕上 【发布时间】:2018-08-24 15:02:27 【问题描述】:

我正在开发一款 androidTV 应用。所以我有一个包含 5 个项目的水平线性布局的 recyclerview。在 OnBindViewHolder 期间,我调用 viewholder.bind() 并在其中动态更改各个项目的宽度。然后我调用 getLocalVisibleRect() 来查看哪些视图实际上在屏幕上。这是问题所在。它适用于初始屏幕,但是当我向下滚动回收视图时,它与它们是否在屏幕上的结果不一致。这是我设置项目长度的地方,并尝试将其设置为可聚焦,无论它是否在屏幕上。

    private void setProgramDataToView(Programme programme, TextView textView) 
        textView.setText(getEPGText(programme));
        textView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() 
            @Override
            public void onGlobalLayout() 
                Rect r = new Rect();
                boolean v = textView.getLocalVisibleRect(r);
                textView.setFocusable(v);
                textView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            
        );

        ViewGroup.LayoutParams layoutParams = textView.getLayoutParams();
        layoutParams.width = timeLineHelper.getDurationProgram(programme);
        textView.setLayoutParams(layoutParams);
    

我尝试在更改长度之前或之后将 GlobalLayoutListener 更改为,看起来并没有什么不同。而且由于它适用于最初的 recyclerview 项目,因此逻辑似乎有效。看起来这可能是一种竞争条件,但是在滚动某些项目时会给出正确的结果,而其余的则非常不一致。例如,它会说屏幕上的视图不在屏幕上,而屏幕外的视图在屏幕上。任何帮助将不胜感激。

【问题讨论】:

您有什么理由不使用findFirstVisibleItemPosition 和findLastVisibleItemPosition 来确定屏幕上的视图吗? recyclerview 是垂直的,但是每个项目都有一个水平的线性布局,这就是我希望看到哪些线性布局子项在屏幕上。我继承了这段代码,所以不确定他们为什么这样做。我发布了我的解决方案。 我知道你继承了代码,但是你能改变它吗?我可以发布一个简单的方法来检查屏幕上的 RecyclerView 布局是否可以使用。这是一种标准的做法。 我现在有一个对我有用的方法,但我也想看看你的方法是否更好。目前我的非常密集,因为它经常设置可聚焦性(每次按下 DPAD_RIGHT 时)。 我可以给你一个方法,当被调用时,它将返回屏幕上第一个和最后一个 RecyclerView 孩子的适配器位置。你能用它吗? 【参考方案1】:

这是您发布的isViewOnScreen() 方法的替代方法。它使用RecyclerView 的布局管理器将可见视图括起来,然后检查以确保相关视图的适配器位置被这些位置括起来。见doc for these methods。

private boolean isViewOnScreen(RecyclerView rv, View view) 
    // Assuming a LinearLayoutManager but it could be another type.
    LinearLayoutManager lm = (LinearLayoutManager) recyclerView.getLayoutManager();
    int firstVisiblePosition = lm.findFirstVisibleItemPosition();
    int lastVisiblePosition = lm.findLastVisibleItemPosition();
    int viewPosition = lm.getPosition(view);
    return viewPosition >= firstVisiblePosition && viewPosition <= lastVisiblePosition;

【讨论】:

当我们到达getPosition 线时,这对我来说崩溃了【参考方案2】:

我最终只是在使用 recyclerview 的片段中检查 OnKeyDown 期间屏幕上显示了哪些视图。这在计算方面有点过分,但对我的情况有效。这样可以确保在检查视图是否在屏幕上之前完全绘制视图。

private boolean setOnScreenViewsFocusable(View focus) 
    View parentView = (View) focus.getParent();
    if (parentView.getId() != View.NO_ID && parentView.getId() == R.id.channel_item) 
        LinearLayout parentLayout = (LinearLayout) parentView;
        for (int i = 1; i < 6; i++) 
            parentLayout.getChildAt(i).setFocusable(isViewOnScreen(parentLayout.getChildAt(i)));
        
    
    return false;


private boolean isViewOnScreen(View view) 
    Rect r = new Rect();
    return view.getGlobalVisibleRect(r);

【讨论】:

以上是关于在回收站视图中查找视图是不是在屏幕上的主要内容,如果未能解决你的问题,请参考以下文章

从回收视图中将回收视图项目添加到另一个屏幕 - kivy

过渡动画无法从回收视图到详细信息屏幕

RecyclerView 在回收视图时不尊重翻译

在回收站视图中滚动时,它向选定的复选框列表添加了一些其他值

我正在使用融合位置 API 在回收视图适配器中查找当前位置,适配器由片段类使用

水平回收视图捕捉到中心,同时显示上一个/下一个项目