RecyclerView / VerticalGridView 焦点移动时视图形变的问题

前言

        在某些情况下,我们需要将装载数据的 RecyclerView 或 leanback-VerticalGridView 控件固定在特定尺寸下,以充分利用屏幕尺寸。

        但在固定尺寸后,进行焦点移动时,往往会存在 Item 被切超出布局的问题,即:焦点移动时视图形变的问题。本文为此问题提供了一个解决办法,下面来看看具体问题和解决办法。

需求描述

        如下图,需要用列表控件装载已配对的设备(即:图中 Paired devices下面的列表内容),我们可以使用 ListView 或 RecyclerView,但在 TV 上显然我们有更好的选择,即 leanback 系列的 VerticalGridView,这三个控件可以依自身情况使用,但是都会存在焦点移动时视图形变的问题。

 实现效果

1. Item 被切

        Item 被切很好理解,因为我们对 Item 聚焦时做了放大动效,会超出布局尺寸,此时在父控件设置 clipChildren 为 false,让其不进行裁剪即可。

2. 超出布局 

3. 正常效果

 问题解析

        前文提到了我们可以轻而易举解决 Item 被切的问题,但对于超出布局这题却没有好的解决办法——列表+固定布局+聚焦放大动效。

        目前我这边想到一种方式并在实战中使用,虽然稍显蹩脚,但能较好满足需求。下面看一下两者的代码,分析不同之处,解决思路显而易见。

超出布局时 XML 代码如下        

<androidx.leanback.widget.VerticalGridView
    android:id="@+id/vgv_ble_paired"
    android:layout_width="@dimen/size_1112_base"
    android:layout_height="@dimen/size_280_base"
    android:layout_marginStart="@dimen/size_206_base"
    android:layout_marginTop="@dimen/size_24_base"
    android:clipChildren="false" />

正常效果时 XML 代码如下

<FrameLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginStart="@dimen/size_161_base"
    android:layout_marginTop="@dimen/size_19_base">
 
    <androidx.leanback.widget.VerticalGridView
        android:id="@+id/vgv_ble_paired"
        android:layout_width="@dimen/size_1202_base"
        android:layout_height="@dimen/size_290_base"
        android:clipChildren="false"
        android:clipToPadding="false"
        android:paddingStart="@dimen/size_45_base"
        android:paddingTop="@dimen/size_5_base"
        android:paddingEnd="@dimen/size_45_base"
        android:paddingBottom="@dimen/size_5_base" />
</FrameLayout>

细节讨论

        需求 UI 图中了解到,列表总高度为 280px,总宽度为 1112px,左间距为 206px,上间距为 24px,如上面超出布局时的 XML 布局代码所示。

        正如软件中遇到解决不了的问题时,加一个中间件往往可以使问题迎刃而解,所以这里采取的解决方案如斯简单粗暴——加一个中间层 FrameLayout 

        Framelayout 限定对外布局尺寸,而 VerticalGridView 通过设置 padding 对内限定超出布局即可,这里保证列表整体位置不变即可,有如下逻辑需注意:

  • paddingStart 和 paddingEnd 的值应为聚焦放大后超出布局的宽度,同理, paddingTop 和 paddingBottom 的值应为聚焦放大后超出布局的高度;
  • VerticalGridView 的 paddingStart 与 Framelayout 的 layout_marginStart 之和,应为 UI 图中列表左间距 206px;
  • VerticalGridView 的宽高需要加上左右和上下的 padding 距离;
  • VerticalGridView 的 clipChildren 和 clipToPadding 都为 false。

小结

        本问题主要在 Android TV 或投影仪等硬件设备上出现,且本文所采取方案并不是最终解决办法,请慎重使用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值