转载:http://blog.csdn.net/wzlas111/article/details/39741091

Android TV上的焦点凸显特效相信大家都看到过,那么我们就来实现它吧,首先上张效果图。

先说一下实现原理,主要通过重写RelativeLayout实现item,之后在其中加入scalanimation动画效果。刚开始处理时,还是发现了一些问题,比如item放大后会被其他item遮挡,如何添加选中边框等等,以及动画的实现等等。下面放上实现细节。

首先是item的代码:

  1. <view xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:id="@+id/item"
  3. android:layout_width="@dimen/home_channel_item_width"
  4. android:layout_height="@dimen/home_channel_item_height"
  5. class="com.eastelsoft.tv.widget.home.HomeItemContainer"
  6. android:clickable="true"
  7. android:focusable="true"
  8. android:focusableInTouchMode="true"
  9. android:clipChildren="false"
  10. android:clipToPadding="false" >
  11. <com.eastelsoft.tv.widget.ESImageView
  12. android:id="@+id/img"
  13. android:layout_width="fill_parent"
  14. android:layout_height="fill_parent"
  15. android:background="@drawable/holder_nor"
  16. android:duplicateParentState="true"
  17. android:scaleType="fitXY" />
  18. <!-- -->
  19. <com.eastelsoft.tv.widget.ESImageView
  20. android:id="@+id/hover"
  21. android:layout_width="fill_parent"
  22. android:layout_height="fill_parent"
  23. android:contentDescription="@string/desc"
  24. android:duplicateParentState="true"
  25. android:scaleType="fitXY"
  26. android:src="@drawable/sl_image_home_navigator" />
  27. <TextView
  28. android:id="@+id/text"
  29. android:layout_width="fill_parent"
  30. android:layout_height="wrap_content"
  31. android:layout_alignParentBottom="true"
  32. android:layout_marginBottom="@dimen/home_item_text_margin"
  33. android:layout_marginLeft="@dimen/home_item_text_margin"
  34. android:layout_marginRight="@dimen/home_item_text_margin"
  35. android:ellipsize="marquee"
  36. android:gravity="bottom|right|center"
  37. android:includeFontPadding="false"
  38. android:marqueeRepeatLimit="5"
  39. android:maxWidth="@dimen/px310"
  40. android:shadowColor="#88333333"
  41. android:shadowDx="2.0"
  42. android:shadowDy="2.0"
  43. android:shadowRadius="2.0"
  44. android:singleLine="true"
  45. android:textColor="#ffffffff" />
  46. </view>

这里定义了一个自定义view,代码在后面放上,每个item里添加了一个img,用于放置内容图片,一个hover,用于显示选中的边框,以及一个text,显示一些文字说明。

hover的src是一个selector drawable,当未focus时,它的背景是tansparent,当focus,放入外框图片。

自定义的HomeItemContainer 代码:

  1. public class HomeItemContainer extends RelativeLayout {
  2. private Rect mBound;
  3. private Drawable mDrawable;
  4. private Rect mRect;
  5. private Animation scaleSmallAnimation;
  6. private Animation scaleBigAnimation;
  7. public HomeItemContainer(Context context) {
  8. super(context);
  9. init();
  10. }
  11. public HomeItemContainer(Context context, AttributeSet attrs, int defStyle) {
  12. super(context, attrs, defStyle);
  13. init();
  14. }
  15. public HomeItemContainer(Context context, AttributeSet attrs) {
  16. super(context, attrs);
  17. init();
  18. }
  19. protected void init() {
  20. setWillNotDraw(false);
  21. mRect = new Rect();
  22. mBound = new Rect();
  23. mDrawable = getResources().getDrawable(R.drawable.poster_shadow_4);//nav_focused_2,poster_shadow_4
  24. setChildrenDrawingOrderEnabled(true);
  25. }
  26. @Override
  27. protected void onAttachedToWindow() {
  28. super.onAttachedToWindow();
  29. }
  30. @Override
  31. public void draw(Canvas canvas) {
  32. super.draw(canvas);
  33. }
  34. @Override
  35. protected void onDraw(Canvas canvas) {
  36. if (hasFocus()) {
  37. System.out.println("HomeItemContainer focus : true ");
  38. super.getDrawingRect(mRect);
  39. mBound.set(-39+mRect.left, -39+mRect.top, 39+mRect.right, 39+mRect.bottom);
  40. mDrawable.setBounds(mBound);
  41. canvas.save();
  42. mDrawable.draw(canvas);
  43. canvas.restore();
  44. }
  45. super.onDraw(canvas);
  46. }
  47. @Override
  48. protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
  49. super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
  50. if (gainFocus) {
  51. bringToFront();
  52. getRootView().requestLayout();
  53. getRootView().invalidate();
  54. zoomOut();
  55. } else {
  56. zoomIn();
  57. }
  58. }
  59. private void zoomIn() {
  60. if (scaleSmallAnimation == null) {
  61. scaleSmallAnimation = AnimationUtils.loadAnimation(getContext(), R.anim.anim_scale_small);
  62. }
  63. startAnimation(scaleSmallAnimation);
  64. }
  65. private void zoomOut() {
  66. if (scaleBigAnimation == null) {
  67. scaleBigAnimation = AnimationUtils.loadAnimation(getContext(), R.anim.anim_scale_big);
  68. }
  69. startAnimation(scaleBigAnimation);
  70. }
  71. }

注意onFocusChanged方法,为防止item被其他item遮挡,先调用bringToFront方法,使此item处于最上层,之后调用父view的方法进行重新绘制,其实注意一点,item必须处于同一父view中,否则requestLayout和invalidate可能会不起作用,只适用于RelativeLayout布局,经测试LinearLayout不适用。

顺便放上一个scaleanimation缩小的效果代码:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <set xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:fillAfter="false"
  4. android:fillBefore="true"
  5. android:shareInterpolator="false" >
  6. <scale
  7. android:duration="200"
  8. android:fromXScale="1.1"
  9. android:fromYScale="1.1"
  10. android:interpolator="@android:anim/accelerate_decelerate_interpolator"
  11. android:pivotX="50.0%"
  12. android:pivotY="50.0%"
  13. android:repeatCount="0"
  14. android:toXScale="1.0"
  15. android:toYScale="1.0" />
  16. </set>

里面的属性就不详细介绍了,有兴趣的可以自己谷歌。

最后放上item的父view:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="horizontal"
  6. android:padding="10dp"
  7. android:clipChildren="false"
  8. android:clipToPadding="false" >
  9. <include
  10. android:id="@+id/channel_0"
  11. android:layout_width="@dimen/home_channel_item_width"
  12. android:layout_height="@dimen/home_channel_item_height"
  13. layout="@layout/home_page_channel_item"
  14. android:layout_alignParentLeft="true"
  15. android:layout_alignParentTop="true"
  16. android:layout_margin="3dp" />
  17. <include
  18. android:id="@+id/channel_1"
  19. android:layout_width="@dimen/home_channel_item_width"
  20. android:layout_height="@dimen/home_channel_item_height"
  21. layout="@layout/home_page_channel_item"
  22. android:layout_below="@id/channel_0"
  23. android:layout_alignLeft="@id/channel_0" />
  24. <include
  25. android:id="@+id/channel_2"
  26. android:layout_width="@dimen/home_channel_item_width"
  27. android:layout_height="@dimen/home_channel_item_height"
  28. layout="@layout/home_page_channel_item"
  29. android:layout_toRightOf="@id/channel_0"
  30. android:layout_alignTop="@id/channel_0"
  31. android:layout_marginRight="3dp"
  32. android:layout_marginBottom="3dp"/>
  33. <include
  34. android:id="@+id/channel_3"
  35. android:layout_width="@dimen/home_channel_item_width"
  36. android:layout_height="@dimen/home_channel_item_height"
  37. layout="@layout/home_page_channel_item"
  38. android:layout_alignLeft="@id/channel_2"
  39. android:layout_below="@id/channel_2"/>
  40. <include
  41. android:id="@+id/channel_4"
  42. android:layout_width="@dimen/home_channel_item_width"
  43. android:layout_height="@dimen/home_channel_item_height"
  44. layout="@layout/home_page_channel_item"
  45. android:layout_toRightOf="@id/channel_2"
  46. android:layout_alignTop="@id/channel_2"
  47. android:layout_marginRight="3dp"
  48. android:layout_marginBottom="3dp"/>
  49. <include
  50. android:id="@+id/channel_5"
  51. android:layout_width="@dimen/home_channel_item_width"
  52. android:layout_height="@dimen/home_channel_item_height"
  53. layout="@layout/home_page_channel_item"
  54. android:layout_alignLeft="@id/channel_4"
  55. android:layout_below="@id/channel_4"/>
  56. <include
  57. android:id="@+id/channel_6"
  58. android:layout_width="@dimen/home_channel_item_width"
  59. android:layout_height="@dimen/home_channel_item_height"
  60. layout="@layout/home_page_channel_item"
  61. android:layout_toRightOf="@id/channel_4"
  62. android:layout_alignTop="@id/channel_4"
  63. android:layout_marginRight="3dp"
  64. android:layout_marginBottom="3dp"/>
  65. <include
  66. android:id="@+id/channel_7"
  67. android:layout_width="@dimen/home_channel_item_width"
  68. android:layout_height="@dimen/home_channel_item_height"
  69. layout="@layout/home_page_channel_item"
  70. android:layout_alignLeft="@id/channel_6"
  71. android:layout_below="@id/channel_6"/>
  72. <include
  73. android:id="@+id/channel_8"
  74. android:layout_width="@dimen/home_channel_item_width"
  75. android:layout_height="@dimen/home_channel_item_height"
  76. layout="@layout/home_page_channel_item"
  77. android:layout_toRightOf="@id/channel_6"
  78. android:layout_alignTop="@id/channel_6"
  79. android:layout_marginRight="3dp"
  80. android:layout_marginBottom="3dp"/>
  81. <include
  82. android:id="@+id/channel_9"
  83. android:layout_width="@dimen/home_channel_item_width"
  84. android:layout_height="@dimen/home_channel_item_height"
  85. layout="@layout/home_page_channel_item"
  86. android:layout_alignLeft="@id/channel_8"
  87. android:layout_below="@id/channel_8"/>
  88. </RelativeLayout>

这里我定义了10个item,注意RelativeLayout的两个属性,clipChildren设置false,让children view可以超出自身所设置的大小,clipToPadding设置为false,让children view可以使用padding 的位置进行绘制,有了这2个属性,item就可以实现放大而不被遮挡了。

好了,焦点特效的教程就说到这里了,有问题可以在评论中反馈。

Android TV上的焦点切换效果的更多相关文章

  1. Android:给ViewPager添加切换效果

    原文参照开发者官网:http://developer.android.com/training/animation/screen-slide.html#viewpager 以App的引导页为例: 首先 ...

  2. android TV选中时高亮凸显效果

    链接: http://pan.baidu.com/s/1pLjAFQ7 密码: xb8g <ignore_js_op> 360手机助手截图0410_18_02_01.png (335.64 ...

  3. Android下Fragment的动画切换效果

    效果图如下: 源码链接   :    请戳这里

  4. React-Native解决ListView 在Android手机上无吸顶效果

    stickySectionHeadersEnabled={true} stickyHeaderIndices={[0]}

  5. Android实现程序前后台切换效果

    本文演示如何在Android中实现程序前后台切换效果. 在介绍程序实现之前,我们先看下Android中Activities和Task的基础知识. 我们都知道,一个Activity 可以启动另一个Act ...

  6. Android TV listView焦点平滑移动

    先上TV上效果图 Mark下思路: package com.test.ui; import java.lang.reflect.Method; import android.annotation.Su ...

  7. 两行代码搞定Android视图扩散切换效果

    用最简单的方式来实现Android视图扩散切换效果. 一.概述 这两天时间动手撸了个视图扩散切换效果的控制器,API兼容至Android4.0,更方便我们在视图切换过程中有炫酷的过渡效果.本来是想实现 ...

  8. Android TV开发总结(五)TV上屏幕适配总结

    前言:前面几篇总结一些TV上的小Sample,开源到GitHub:https://github.com/hejunlin2013/TVSample, 点击链接,可以持续关注.今天总结下TV上屏幕适配. ...

  9. Android 自定义 ViewPager 打造千变万化的图片切换效果

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38026503 记得第一次见到ViewPager这个控件,瞬间爱不释手,做东西的主 ...

随机推荐

  1. 亚马逊MWS开发套路演示

    MWS是商城网络服务的缩写,具体介绍看这里http://docs.developer.amazonservices.com/zh_CN/dev_guide/DG_IfNew.html.MWS就是一组A ...

  2. DeepLearning4J 环境搭建【转】

    深度学习Deeplearning4j eclipse 开发环境搭建 eclipse设置deeplearning4j开发环境:手动添加jar包 https://deeplearning4j.org/cn ...

  3. Unit02: JSON 、 使用JSON实现数据交换 、 jQuery对AJAX的支持,编码问题

    Unit02: JSON . 使用JSON实现数据交换 . jQuery对AJAX的支持 1. 编码问题 (1)发送get请求 为什么会产生乱码? ie浏览器提供的ajax对象,对中文会使用gbk来编 ...

  4. 在Google的GKE上创建支持Internal Load Balancer的Service

    在Google的Kubernetes Engine上发布service,可以采用除On-Promise相同的Cluster IP和NodePort两种方式外,还可以创建LoadBalaner的Serv ...

  5. 谈谈对zynq的浅显理解

    zynq并不能说是一个嵌入arm核的FPGA.从它的启动过程就可以发现,绝对是arm主导的,所以称它为以高性能FPGA为外设的双核arm或许更为合适.以下是优势: 第一个:开发环境的大集成.从hls到 ...

  6. Redis:目录

    ylbtech-Redis:目录 1.返回顶部   2.返回顶部   3.返回顶部   4.返回顶部   5.返回顶部     6.返回顶部   7.返回顶部   8.返回顶部   9.返回顶部   ...

  7. (转)CentOS 7安装Zabbix 3.4

    (转)Zabbix 3.4 支持Centos 7.貌似不支持6.9. 更多详细内容请参考官方说明文档,详细的安装要求不贴出来了. https://www.zabbix.com/documentatio ...

  8. 使用DOSGi在OSGi环境下发布Web Services

    前言 Apache CXF是一个开源的服务框架项目,而Distributed OSGi子项目提供了基于OSGi远程服务规范的分布式组件实现.它使用Web Services,HTTP上的SOAP手段实现 ...

  9. [置顶] ubuntu版本很老,apt-get update更新失败时(W: Failed to fetch ...)------如何创建新的sources.list

    在说这个解决方案之前,我先说下,目前遇到的问题: 我使用 sudo apt-get update 之后,更新失败.具体原因如下: W: Failed to fetch http://cn.archiv ...

  10. 【POJ】2373 Dividing the Path(单调队列优化dp)

    题目 传送门:QWQ 分析 听说是水题,但还是没想出来. $ dp[i] $为$ [1,i] $的需要的喷头数量. 那么$ dp[i]=min(dp[j])+1 $其中$ j<i $ 这是个$ ...