Android TV Rows支持Fragment居中第一个和最后一个项目以及无限滚动

问题描述 投票:0回答:1

所以我正在做一个 Android TV 应用程序,它基本上是一个充满电视剧和电影的主屏幕,就像任何其他传统视频流应用程序一样。 为此,我所做的就是简单地将

RowsSupportFragment
与多行和多个演示者一起使用,因为我必须更改每行的
UI
。例如:第一行是
Billboards
行,第二行是
continue watching list
,然后是带有纯图像的所有常见行

对于这个特定的

Billboards
行,我需要在这两点上模仿旧的轮播行为:

  1. 我需要将所有项目集中在屏幕中间,这里唯一的大问题是第一个和最后一个项目,因为它看起来更多在屏幕边缘。我需要找到一种方法将这些项目放在中间。
  2. 我需要以某种方式循环所有行,就像我在最后一项,如果我按 DPAD Right,它需要返回到第一个元素,如果我在第一项,按 DPAD Left,我必须转到最后一项,但就像无限滚动。

不确定是否可以使用 Android TV 中的 Leanback 库来做到这一点,因为我真的对此迷失了。我能够通过这样做获得每行的 gridView :

private fun getBillboardGridView(): HorizontalGridView? {
    val billboardRowPosition = 0
    val billboardContainer = verticalGridView?.get(billboardRowPosition )
    return ((billboardContainer as? ViewGroup)?.get(1) as? ListRowView)?.gridView
}

and do something like:

private fun someTest(): HorizontalGridView? {
    getBillboardGridView()?.smoothScrollToPosition(anyPosition)
}

但无法对此做任何事情

HorizontalGridView
...

编辑:对于第 1 点,我可以通过使用来实现它:

gridView?.windowAlignment = BaseGridView.WINDOW_ALIGN_NO_EDGE
gridView?.windowAlignmentOffsetPercent = 25f

提前感谢您的帮助

android android-tv leanback
1个回答
0
投票

希望你一切都好!

我找到了一种在 Billboard HorizontalGridView 上模拟无限滚动的方法。

首先,当我们为行项目创建列表时,我们将最后一个项目的副本添加到列表的开头,并将第一个项目的副本附加到列表的末尾。

fun createBillboard(displayOrder: Int?, billboardList: List<PublishListItemDisplayName>): RowItem {
    val cardRow = RowItem(RowItem.RowType.TYPE_BILLBOARD)
    val sortedBillboards = billboardList.sortedBy { it.displayOrder }

    cardRow.cards = if (sortedBillboards.size >= 3) { // For billboard infinite scroll
        listOf(
            sortedBillboards.last(),
            *sortedBillboards.toTypedArray(),
            sortedBillboards.first(),
        )
    } else {
        billboardList.sortedBy { it.displayOrder }
    }
    cardRow.displayOrder = displayOrder
    return cardRow
}

然后,当我们初始化 Billboard 时,我们添加一个子选择侦听器,如果第一个项目获得焦点,则焦点将转移到倒数第二个项目,如果最后一个项目获得焦点,焦点将转移到倒数第二个项目,从而创建无限滚动但元素有限的错觉。

注意,如果我们有 3 个或更多元素,此方法效果最佳,理想情况下,我们应该将默认焦点设置为中间的子元素。希望这有帮助!

gridView.setOnChildViewHolderSelectedListener(object: OnChildViewHolderSelectedListener() {
    override fun onChildViewHolderSelected(parent: RecyclerView?, child: RecyclerView.ViewHolder?, position: Int, subposition: Int) {
        Timber.i("Selected position: $position")
        billboardList?.let hold@ {
            if (size < 3) return@hold
            when (position) {
                0 -> gridView.selectedPosition = size - 2
                size - 1 -> gridView.selectedPosition = 1
            }
        }
        super.onChildViewHolderSelected(parent, child, position, subposition)
    }
})
© www.soinside.com 2019 - 2024. All rights reserved.