前言:

AndroidTV中最常见的就是焦点效果,这个实现很简单,在代码设置view.setFocusable(true),布局中focusable="true",然后添加view获得焦点时的效果即可。但是本文不讲这些,而是讲解View获取焦点有一个放大缩小效果,当view放大时处于临近的View之上并且不能被遮挡,当view缩小时要恢复原来的大小。

1.先放几张效果图:

2.方案分析,网上的方案和资料如下:

(1):MainUpView:

(2):MetroItemFrameLayout(何俊林大神的方案):博客地址:Android TV开发总结(一)构建一个TV app前要知道的事儿_欢迎关注公众号:【码农突围】,公号后台回复9999,可以获取一份500页的LeetCode刷题笔记。-CSDN博客

(3)Android tv metro,项目地址:android_tv_metro: android tv metro widget 源码分析

(4)Android tv frame,项目地址:Android-TV-Frame-new: Android TV开发框架 最新版本.

(5)TvRecyclerView,项目地址:https://github.com/henryblue/TvRecyclerView

(6)TvRecyclerView,项目地址:https://github.com/zhousuqiang/TvRecyclerView

(7)TVRecyclerView,项目地址:GitHub - Fredlxy/TVRecyclerView: 运行在Android TV上的RecyclerView

(8)Android tv frame,项目地址:GitHub - songwenju/CustomTvRecyclerView

(9)TvWidget,项目地址:GitHub - evilbinary/TvWidget: tv常用效果控件,包括焦点、边框处理等。

(10)BorderViewDemo,项目地址:https://github.com/lf8289/BorderViewDemo

(11)TvFocusBorder,项目地址:https://github.com/zhousuqiang/TvFocusBorder

(12) Android Tv Widget Demo,项目地址: https://github.com/zhousuqiang/TvWidget

(13)SMTVLauncher,项目地址:GitHub - FrozenFreeFall/SMTVLauncher: 神马视频是一款包含直播、回看、点播、设置于一体的TVLauncher

(14)AndroidTVLauncher,项目地址:GitHub - JackyAndroid/AndroidTVLauncher: This is a leanback style tv launcher(minSdkVersion 17)

(15)TVSample,项目地址:GitHub - smartyuge/TVSample: 1、仿泰捷视频最新TV版 Metro UI效果. 2、仿腾讯视频TV版(云视听·极光) 列表页

(16)Leanback桌面demo,项目地址:https://gitee.com/chuangshiji/Launcher

3.以上方案尝试了一半,由于时间和项目周期问题,所以有些没来得及尝试.

而且接入成本有点大,每个项目都不一样,选择适合自己的才最重要,我们不要拘泥于某一种方案或者第三方库.这里我根据以上方案总结出一份属于我自己的方案,主要代码如下:


4.Fragment完整代码如下:

package com.example.tvrecyclerview.fragment;
​
import android.os.Build;
import android.view.View;
import android.widget.ImageView;
​
import com.example.tvrecyclerview.R;
​
/*** @author: njb* @date: 2020/9/24 0024 0:47* @desc:*/
public class OtherFragment extends FragmentBase implements View.OnFocusChangeListener {private static final float scale0 = 1f;private static final float scaleL = 1.12f;private static final float scaleS = 1.22f;private static final float z1 = 0f;private static final float z2 = 10f;private static final long animateDuration = 20;private static View lastFocus;private ImageView ivRecentControl, ivCollectControl, ivRemoteControl, ivHandleControl, ivQrCodeControl;
​@Overrideprotected int getLayoutRes() {return R.layout.fragment_other;}
​@Overrideprotected void rootViewNoNull() {super.rootViewNoNull();if(null != lastFocus){lastFocus.requestFocus();}}
​@Overrideprotected void initView(View rootView) {super.initView(rootView);//初始化控件ivRecentControl = rootView.findViewById(R.id.iv_my_recent);ivCollectControl = rootView.findViewById(R.id.iv_my_collect);ivHandleControl = rootView.findViewById(R.id.iv_my_handle);ivRemoteControl = rootView.findViewById(R.id.iv_my_remote);ivQrCodeControl = rootView.findViewById(R.id.iv_my_qrcode);//初始化焦点事件ivRecentControl.setOnFocusChangeListener(this);ivCollectControl.setOnFocusChangeListener(this);ivRemoteControl.setOnFocusChangeListener(this);ivHandleControl.setOnFocusChangeListener(this);ivQrCodeControl.setOnFocusChangeListener(this);}
​@Overridepublic void onFocusChange(final View v, boolean hasFocus) {//初始化放大倍数float scaleX1, scaleX2, scaleY1, scaleY2;scaleX1 = scaleY1 = scaleX2 = scaleY2 = scale0;//给获取焦点的view设置倍数if (v.getId() == R.id.iv_my_recent || v.getId() == R.id.iv_my_collect) {scaleX2 = scaleY2 = scaleL;}if (v.getId() == R.id.iv_my_handle || v.getId() == R.id.iv_my_remote || v.getId() == R.id.iv_my_qrcode) {scaleX2 = scaleY2 = scaleS;}//获得焦点时的状态和倍数if (hasFocus) {lastFocus = v;//在android5.0以上的效果if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {v.animate().scaleXBy(scaleX1).scaleX(scaleX2).scaleYBy(scaleY1).scaleY(scaleY2).zBy(z1).z(z2).setDuration(animateDuration);} else {//在android5.0以下的效果v.animate().scaleXBy(scaleX1).scaleX(scaleX2).scaleYBy(scaleY1).scaleY(scaleY2).withEndAction(new Runnable() {@Overridepublic void run() {//防止view被遮挡v.bringToFront();}}).setDuration(animateDuration);}} else {//view在焦点消失后的倍数和状态if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {v.animate().scaleXBy(scaleX2).scaleX(scaleX1).scaleYBy(scaleY2).scaleY(scaleY1).zBy(z2).z(z1).setDuration(animateDuration);} else {v.animate().scaleXBy(scaleX2).scaleX(scaleX1).scaleYBy(scaleY2).scaleY(scaleY1).setDuration(animateDuration);}}}
}

5.布局文件fragment_other.xml代码:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@color/color_blue">
​<includelayout="@layout/layout_more_game"android:layout_width="match_parent"android:layout_height="wrap_content"app:layout_constraintBottom_toBottomOf="parent"app:layout_constraintTop_toTopOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>

6.layout_more_game.xml代码:

<?xml version="1.0" encoding="utf-8"?>
<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:id="@+id/cl_more"android:layout_width="match_parent"android:layout_height="wrap_content"android:padding="20dp"android:layout_marginTop="16dp"android:clipChildren="false"android:clipToPadding="false"tools:ignore="MissingConstraints">
​
​<ImageViewandroid:id="@+id/iv_my_recent"android:layout_width="91dp"android:layout_height="111dp"android:background="@drawable/bg_more_focus"android:focusable="true"android:padding="2dp"android:scaleType="fitXY"android:clipChildren="false"android:clipToPadding="false"android:src="@mipmap/ic_recent"android:layout_marginEnd="16dp"app:layout_constraintLeft_toLeftOf="parent"app:layout_constraintRight_toLeftOf="@+id/iv_my_collect"/>
​
​<ImageViewandroid:id="@+id/iv_my_collect"android:layout_width="91dp"android:layout_height="111dp"android:layout_marginEnd="16dp"android:background="@drawable/bg_more_focus"android:focusable="true"android:padding="2dp"android:scaleType="fitXY"android:clipChildren="false"android:clipToPadding="false"android:src="@mipmap/ic_collect"app:layout_constraintLeft_toRightOf="@+id/iv_my_recent"app:layout_constraintRight_toLeftOf="@id/iv_my_handle"/>
​<ImageViewandroid:id="@+id/iv_my_handle"android:layout_width="0dp"android:layout_height="111dp"android:layout_marginEnd="16dp"android:background="@drawable/bg_more_focus"android:focusable="true"android:padding="2dp"android:scaleType="fitXY"android:clipChildren="false"android:clipToPadding="false"android:src="@mipmap/ic_handle_game"app:layout_constraintLeft_toRightOf="@+id/iv_my_collect"app:layout_constraintRight_toLeftOf="@+id/iv_my_remote"/>
​
​<ImageViewandroid:id="@+id/iv_my_remote"android:layout_width="0dp"android:layout_height="111dp"android:background="@drawable/bg_more_focus"android:focusable="true"android:padding="2dp"android:scaleType="fitXY"android:layout_marginEnd="16dp"android:clipChildren="false"android:clipToPadding="false"android:src="@mipmap/ic_remote_control"app:layout_constraintLeft_toRightOf="@+id/iv_my_handle"app:layout_constraintRight_toLeftOf="@+id/iv_my_qrcode"/>
​<ImageViewandroid:id="@+id/iv_my_qrcode"android:layout_width="0dp"android:layout_height="111dp"android:background="@drawable/bg_more_focus"android:focusable="true"android:padding="2dp"android:scaleType="fitXY"android:clipChildren="false"android:clipToPadding="false"android:src="@mipmap/ic_qrcode_control"app:layout_constraintLeft_toRightOf="@+id/iv_my_remote"app:layout_constraintRight_toRightOf="parent"/>
​
</androidx.constraintlayout.widget.ConstraintLayout>

7.实现的效果图如下:

8.简单分析,要想实现以上效果需要考虑几个问题:

a.放大后的倍数

b.缩小后的倍数

c.view处于临界view之上的边界被切问题

d.在android5.0以上和5.0以下的适配问题

e.封装成一个工具类,因为现在的界面基本上都很复杂,如果是多个布局需要写多个view和倍数等,这样的话每个界面都要写很多次,感觉都是做重复的工作。

9.以上就是TV盒子上的焦点效果实现过程和原理简单分析,后面会出一篇博客详细分析怎么计算倍数,下一篇将会分析怎么封装成一个工具类和封装遇到的问题,欢迎小伙伴们前来讨论留言,有错误指正出来,我会及时更改。

10.项目的源码地址如下:

TvRecyclerView: TV项目,使用recyclerview实现标题切换和焦点效果

AndroidTV开发7实现仿小米电视和各种盒子TV焦点放大缩小效果相关推荐

  1. android camera 动画,android高仿小米时钟(使用Camera和Matrix实现3D效果)

    继续练习自定义View..毕竟熟才能生巧.一直觉得小米的时钟很精美,那这次就搞它~这次除了练习自定义View,还涉及到使用Camera和Matrix实现3D效果. 一个这样的效果,在绘制的时候最好选择 ...

  2. iOS 仿淘宝实现商品规格图片的放大缩小功能

    刚好最近在做个商城项目,甲方爸爸说咱们要求不高,你就照着淘宝来就好,额~~~~ 好吧,咱就不吐槽了,直接开撸吧,惯例先上一下效果图 需求以及思路 我们要实现的功能有如下几个: 图片的全屏查看以及保存 ...

  3. 小米电视产品的最后一个期货:登场脚步快了

    米粉和米黑们Attention! 考验你们专业程度的时候到了:还记得小米在上一次发布会上所有发布的产品中,目前唯一一个还坚挺的停留在期货市场中而迟迟没有面市的是什么嘛?如果绞尽脑汁以后还是想不起来的话 ...

  4. Android开发之高仿QQ消息侧拉删除

    Android开发之高仿QQ消息侧拉删除 QQ消息的侧滑删除效果之炫酷,想必大家都见过吧,本人作为一名安卓开发人员,遇到如此炫酷的效果,怎能不研究一番呢,现本人已实现其基本功能,现将代码贴出,望各位大 ...

  5. 小米电视 android版本升级,小米电视2系统版本多久更新一次

    小米电视2系统版本多久更新一次 40寸.49寸.55寸的小米电视2的MIUI TV操作系统每月升级,每月都有新功能和新体验. 关于小米电视2系统版本多久更新一次的疑问,下面将做详细的解答.49寸的小米 ...

  6. 小米电视刷android系统升级,小米电视2系统版本多久更新一次

    小米电视2系统版本多久更新一次 40寸.49寸.55寸的小米电视2的MIUI TV操作系统每月升级,每月都有新功能和新体验. 关于小米电视2系统版本多久更新一次的疑问,下面将做详细的解答.49寸的小米 ...

  7. 小米电视android刷机,小米电视怎么刷机?小米电视刷第三方系统固件下载

    文件含了所有电视和盒子型号的固件,由于文件没有标明设备名称,所以文件比较大,一并发出.如有想寻找其他小米电视固件或者盒子固件的朋友请一并下载此压缩包,应该会有的. 只有小米4C_32吋,所以其他型号的 ...

  8. patchwall 与鸿蒙对比,官方解读小米电视PatchWall智能电视系统设计的那些事儿

    IT之家1月10日消息 小米于2013年推出小米电视1代MIUI TV版且现在后期不断对已有的电视产品以及UI设计优化才最终成为如今的PatchWall智能电视系统.那么小米电视系统的设计师在整个过程 ...

  9. 安卓TV开发(三) 移动智能设备之实现主流TV电视盒子焦点可控UI

    前言:移动智能设备的发展,推动了安卓另一个领域,包括智能电视和智能家居,以及可穿戴设备的大量使用,但是这些设备上的开发并不是和传统手机开发一样,特别是焦点控制和用户操作体验上有很大的区别,本系列博文主 ...

  10. 仿淘宝Android实现底部导航栏图标溢出效果-clipChildren属性

    1.clipChildren和clipPadding说明 clipChildren用来定义他的子控件是否要在他应有的边界内进行绘制. 默认情况下,clipChild被设置为true. 也就是不允许进行 ...

最新文章

  1. Cocos2d-X中实现菜单特效
  2. mongdb安装使用
  3. 从前端程序员的视角看小程序的稳定性保障
  4. ubuntu 下安装 activate-power-mode
  5. java保留想要的字符,反转Java中的字符,同时保留一些字符 - java
  6. synchronized的用法
  7. 《java练习题》习题集二
  8. chart.js绘制精美的数据化图形--入门示例
  9. 威纶触摸屏使用说明书_MODBUS通信之触摸屏与变频器通信知识分享(一)
  10. MTK 驱动(76)---如何用adb控制MTKLogger
  11. python实时数据存储与显示_利用python进行数据加载和存储
  12. Java 添加、验证PDF 数字签名
  13. Objective-c nil, Nil, NULL和NSNull的区别
  14. 面试常见问题及回答技巧
  15. java 读取485_java通信 485
  16. 会matlab的简历怎么写,算法工程师简历项目经验填写样本
  17. 关于boost和loki的智能指针
  18. 关于行人重识别方法PCB《Beyond Part Models: Person Retrieval with Refined Part Pooling 》及代码实现解读
  19. 关于React报Too many re-renders. React limits the number of renders to prevent an infinite错误的解决方案
  20. 科学计算机算余切,科学计算机在线算(科学计算器如何算正态分布)

热门文章

  1. Python学习路线汇总,必看
  2. 直播网站源码,输入框中显示小图标
  3. SQL 常用语句INSERT INTO,UPDATE,DELETE
  4. Java怎样求解n的阶乘 n!(详解)
  5. Windows PowerShell | 错误: 740 需要提升权限才能运行 DISM
  6. svn文件本地删除 服务器不删,svn delete-删除文件和目录命令大全
  7. modelsim se 10.5安装教程
  8. 装机人员工具/解决局域网共享
  9. ulipad.4.1.zip linux,UliPad 使用介绍
  10. 2014.01.25 JFinal 使用经验积累