Android 电视RecylerView中的循环焦点

Android 电视RecylerView中的循环焦点,android,android-tv,leanback,Android,Android Tv,Leanback,据 您应该将导航顺序设置为循环,以便 控件将焦点引导回第一个焦点 我已尝试为RecyclerView项目实施此类行为: fun RecyclerView.loopFocusVertically() { viewTreeObserver.addOnGlobalLayoutListener { val children = getAllChildren() val firstFocusableItem = children.firstOrNull { it.i

您应该将导航顺序设置为循环,以便 控件将焦点引导回第一个焦点

我已尝试为
RecyclerView
项目实施此类行为:

fun RecyclerView.loopFocusVertically() {
    viewTreeObserver.addOnGlobalLayoutListener {
        val children = getAllChildren()
        val firstFocusableItem = children.firstOrNull { it.isFocusable }
        val lastFocusableItem = children.lastOrNull { it.isFocusable }
        firstFocusableItem?.let { it.nextFocusUpId = lastFocusableItem?.id ?: it.id }
        lastFocusableItem?.let { it.nextFocusDownId = firstFocusableItem?.id ?: it.id }
    }
}
因此,在布局更改时,我使第一个视图对最后一个视图进行了
nextfocuspid
引用,而最后一个视图对第一个视图进行了
nextFocusDownId
引用。但它只适用于所有视图都实际布置在屏幕上的情况,这在一般情况下显然是不正确的
RecyclerView
实际上会回收视图,所以最后一个视图和第一个视图可能不会同时出现在屏幕上

如何在leanback模式下为rv实施聚焦循环? 我曾尝试使用leanback库中的
androidx.leanback.widget.VerticalGridView
,但它也没有必需的行为

默认情况下,从rv焦点的第一个可聚焦项向上按时,会跳转到rv外部的其他可聚焦视图,这不太合适

默认情况下,从rv焦点的第一个可聚焦项向上按时,会跳转到rv外部的其他可聚焦视图,这不太合适

首先,对于用户体验,如果您的列表上方有视图,那么确实会有问题,因此如果您想滚动到最后一项或转到上面的视图,则按向上键确实会有问题

话虽如此,我建议您在这种情况下,如果列表上方有一个视图也应该获得焦点,那么只从底部给出循环选项

一般来说,我建议您检查VerticalGridView/HorizontalGridView,以便在一个精益应用程序中添加行和列表

在本例中,我对其进行了调整,以使用RecyclerView来回答您的问题

为此,您必须捕获button事件,检查它是否是最后一项,如果是,则请求聚焦到第一项

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
    if (event.getAction() == KeyEvent.ACTION_UP) {
        if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_DOWN) {
            if (onDownClick(event)) {
                return true;
            }
        }
    }
    return super.dispatchKeyEvent(ev);
}

public boolean onDownClick(KeyEvent event) {

    int currentIndex = 0;

    if (mAdapter != null) {
        currentIndex = mAdapter.indexOf(mCurrentItem);
    }

    if (currentIndex == mAdapter.size() - 1) {
        mListRecycler.scrollToPosition(0);
        if (mListRecycler.findViewHolderForAdapterPosition(0) != null) {
            mListRecycler.findViewHolderForAdapterPosition(0).itemView.requestFocus();
        }
        return true;
    }

    return false;
}