转载: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. Python——基础数据类型(补充)

    1.基础数据类型汇总补充 (1)小数据池:   为了节省空间,数字和字符串有,其他的没有[了解]   数字:-5---256之间的数字共用一个内存地址 #(1)i1 = i2 id(i1) == id ...

  2. Mac环境下PHPstorm配置xdebug开发调试web程序

    一.安装PHP的xdebug扩展 安装xdebug(技巧,为了找到适配的版本,让xdebug网站根据phpinfo()函数输出分析找到对应的方法及安装步骤:如果安装了多个PHP版本的话,尽量用phpi ...

  3. GOF23设计模式之解释器模式(interpreter)

    一.解释器模式概述 (1)它是一种不常用的设计模式: (2)由于描述如何构成一个简单的语言解释器,主要用于使用面向对象语言开发的编译器和解释器的设计: (3)当我们需要开发一种新的语言时,可以考虑使用 ...

  4. MSYS2环境搭建

    本机环境:Windows XP 32位MSYS2地址:http://sourceforge.net/projects/msys2/ 下载32位版本,地址:http://sourceforge.net/ ...

  5. java代码----------计算器代码

    总结: 很多不完善—— package com.rue; import java.awt.BorderLayout; import java.awt.FlowLayout; import java.a ...

  6. 一个jquery-ajax post例子ajax 登陆

    index.html文件 <html> <head> <meta http-equiv="Content-Type" content="te ...

  7. iRedMail的搭建过程记录

    iRedMail的搭建和注意事项 经过一段时间的折腾,终于将iRedMail搭建起来了,下面介绍一下搭建的过程,以及注意事项. 注意事项:  1. iRedMail不支持重复安装,如果安装错误,请重置 ...

  8. docker 学习(十) 容器常用命令

    1  docker run -it ubuntu:15.10 /bin/bash 如果有ubuntu:15.10这个镜像,就run,否则会从dockerhub下载,并run. -it 一般连用,表示按 ...

  9. node.js 获取客户端信息

    结果:

  10. [CSAPP] Chapter 1 Overview of Computer

    1.1 information is bits + context All computer programs are just a sequence of bits, each with a val ...