【Android TV 开发】–>Leanback 中的 HorizontalGridView

【Android TV 开发】–>Leanback 中的 HorizontalGridViewLeanBack 是 Google 官方推出的 TV 端的功能库 里面包含了很多在 TVAndroid 端开发常用的控件 本文重点介绍其对 RecyclerView 适配 TV 端做的封装 HorizontalGr

不断学习,做更好的自己!?

视频号 CSDN 简书
欢迎打开微信,关注我的视频号:KevinDev 点我 点我

LeanBack 是 Google 官方推出的 TV 端的功能库,里面包含了很多在 TV Android 端开发常用的控件,本文重点介绍其对 RecyclerView 适配 TV 端做的封装:HorizontalGridView 。

效果图

在这里插入图片描述

属性 & 方法

  • focusOutFront、focusOutEnd
    如果标题栏使用 HorizontalGridView 实现,内容区域使用 Fragment 里放的 VerticalGridView 实现,可能出现标题栏和内容区焦点切换不成功的问题,比如说,焦点不能从内容区切到标题栏这样的情况。这时使用 focusOutFront 和 focusOutEnd 属性能够解决问题,解决不同容器里焦点切换不成功的问题。

  • setHorizontalSpacing()
    设置 HorizontalGridView 的 Item 之间的间距。

  • setFocusScrollStrategy()
    设置焦点的滚动方式,它的参数有3个可选值,默认值为 FOCUS_SCROLL_ALIGNED;

    • FOCUS_SCROLL_ALIGNED:焦点在中间
    • FOCUS_SCROLL_ITEM:焦点在末尾
    • FOCUS_SCROLL_PAGE:翻页
  • setNumRows()
    设置行数,默认 HorizontalGridView 为一行,通过 setNumRows 方法可以设置多行。但有个注意点,设置多行后要注意 position 的位置。

  • setRowHeight()
    设置 HorizontalGridView 的 Item 的高度,而不是用来设置 HorizontalGridView 的高度。

  • setSelectedPosition()、setSelectedPositionSmooth()
    让某个 position 获取焦点,区别在于 setSelectedPositionSmooth 在移动时更平滑一点。

  • duplicateParentState()
    它的放大的焦点 View 是每个 Item 的最外层布局,而不是图标那个View,但是其焦点框却套在了图标那个 View 上,那这种效果如果我来实现就会用到 duplicateParentState 属性了。duplicateParentState 的意思是:当前控件是否跟随父控件的(点击、焦点等)状态。

基本使用

1. 添加依赖

 implementation 'androidx.leanback:leanback:1.0.0' implementation 'androidx.leanback:leanback-preference:1.0.0' 

2. 布局文件

  • bg_title.xml
 
    <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/btn_focus" android:state_focused="true" />  
     selector> 
  • btn_focus.xml
 
    <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:radius="300dp" /> <solid android:color="#FF4081" />  
     shape> 
  • activity_widget.xml
 
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@color/teal_200" tools:context=".widget.WidgetActivity"> <androidx.leanback.widget.HorizontalGridView android:id="@+id/hg_title" android:layout_width="wrap_content" android:layout_height="50dp" app:focusOutEnd="true" app:focusOutFront="true" tools:ignore="MissingConstraints" />  
     androidx.constraintlayout.widget.ConstraintLayout> 
  • item_title.xml
 
    <TextView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="match_parent" android:background="@drawable/bg_title" android:clickable="true" android:focusable="true" android:gravity="center" android:textColor="#FFFFFF" android:focusableInTouchMode="true" android:paddingLeft="30dp" android:paddingRight="30dp" android:textSize="28sp" /> 

3. 创建 Presenter

/ * Created on 2022/4/16 17:51 * * @author Gong Youqiang */ public class TitlePresenter extends Presenter { 
    @Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup) { 
    View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_title, viewGroup, false); return new ViewHolder(view); } @Override public void onBindViewHolder(Presenter.ViewHolder viewHolder, Object o) { 
    if (o instanceof Title) { 
    ViewHolder vh = (ViewHolder) viewHolder; vh.tvTitle.setText(((Title) o).getName()); } } @Override public void onUnbindViewHolder(Presenter.ViewHolder viewHolder) { 
    } static class ViewHolder extends Presenter.ViewHolder { 
    TextView tvTitle; public ViewHolder(View view) { 
    super(view); tvTitle = view.findViewById(R.id.tv_title); } } } 

4. Title.java

/ * Created on 2022/4/16 17:53 * * @author Gong Youqiang */ public class Title { 
    private String name; public Title(String name) { 
    this.name = name; } public String getName() { 
    return name; } public void setName(String name) { 
    this.name = name; } } 

5. TitleModel

/ * Created on 2022/4/16 17:53 * * @author Gong Youqiang */ public class TitleModel { 
    public static List<Title> getTitleList() { 
    List<Title> titleList = new ArrayList<>(); titleList.add(new Title("儿童模式")); titleList.add(new Title("家庭模式")); titleList.add(new Title("商务模式")); return titleList; } } 

6. 使用

public class WidgetActivity extends AppCompatActivity { 
    @BindView(R.id.hg_title) HorizontalGridView horizontalGridView; @SuppressLint("RestrictedApi") @Override protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); setContentView(R.layout.activity_widget); ButterKnife.bind(this); horizontalGridView.setHorizontalSpacing(30); ArrayObjectAdapter arrayObjectAdapter = new ArrayObjectAdapter(new TitlePresenter()); ItemBridgeAdapter itemBridgeAdapter = new ItemBridgeAdapter(arrayObjectAdapter); horizontalGridView.setAdapter(itemBridgeAdapter); horizontalGridView.setFocusScrollStrategy(BaseGridView.FOCUS_SCROLL_ITEM); arrayObjectAdapter.addAll(0, TitleModel.getTitleList()); } } 
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/211284.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月18日 下午10:47
下一篇 2026年3月18日 下午10:47


相关推荐

  • Java 审计之xss审计要点

    Java审计之xss审计要点0x00前言上篇文章讲了xss的一个简单审计,这篇文章可以来复盘一下上篇文章内容在上篇文章基础上做一个详细说明,以及其他的一些审计姿势。首发:Java审计之XSS

    2021年12月12日
    266
  • 2020Web应用防火墙 (WAF)榜单TOP30

    2020Web应用防火墙 (WAF)榜单TOP30WAF市场的发展缘于客户需要保护内外的Web应用程序。WAF保护Web应用程序和API免受各种攻击,包括自动机器人程序、注入攻击和应用层拒绝服务(DoS)攻击。它们应提供基于特征(signature)的防护,还应支持主动安全模型(自动化允许列表)及/或异常检测。Gartner报告曾指出,在保护企业Web应用最有效的技术中,WAF高居首位(73%),成为可显著降低Web应用漏洞风险、满足安全合规和等级保护要求的重要手段。因此WAF市场仍然充满活力,许多提供商声称迎来两位数的强劲增长。Gartner观察到

    2022年6月2日
    64
  • QThread的用法

    概述QThread类提供了一个与平台无关的管理线程的方法。一个QThread对象管理一个线程。QThread的执行从run()函数的执行开始,在Qt自带的QThread类中,run()函数通过调用exec()函数来启动事件循环机制,并且在线程内部处理Qt的事件。在Qt中建立线程的主要目的就是为了用线程来处理那些耗时的后台操作,从而让主界面能及时响应用户的请求操作。下面就谈谈如何利用QT

    2022年4月3日
    95
  • Cursor vs GitHub Copilot vs VS Code:怎么选、怎么搭配、怎么把风险关在笼子里

    Cursor vs GitHub Copilot vs VS Code:怎么选、怎么搭配、怎么把风险关在笼子里

    2026年3月16日
    2
  • Union用法及说明:

    Union用法及说明:

    2021年10月15日
    38
  • crane:字典项与关联数据处理的新思路[通俗易懂]

    crane:字典项与关联数据处理的新思路[通俗易懂]前言在我们日常开发中,经常会遇到一些烦人的数据关联和转换问题,比如典型的:对象属性中个有字典id,需要获取对应字典值并填充到对象中;对象属性中有个外键,需要关联查询对应的数据库表实体,并获取其

    2022年8月16日
    9

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号