转载: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. Extjs tree2

    本案例中记载了Extjs中一棵树的形成以及各种案例集成,并详解介绍了TreePanel.TreeNode和AsyncTreeNode这三个主要对象.纯属个人业余时间玩玩的,整理出来,方便以后查看. J ...

  2. python从网络时间服务器获取并打印当前时间以及pip安装ntplib的一次体验

    首先需要安装ntplib,科一通过pip安装. ubuntu下科一通过如下指令安装pip: $ sudo apt-get install python-pip 使用如下指令安装ntplib: $ su ...

  3. pandas之DateFrame

    float_df = pd.DataFrame((0.45*np.arange(1,9)).reshape(4,2), index=[1,2,3,4], columns=['col_one', 'co ...

  4. opencv读取中文路径报错的问题

    ) ## 经验证,不需要再转bgr,myImread的读图结果已经是和imread一样的 return img

  5. jeecg中List页面的高级查询

    1.普通的高级查询 <t:datagrid name="orderworthList" title="订单价值统计" actionUrl="or ...

  6. Django 组件-用户认证

    用户认证 auth模块 from django.contrib import auth 1.1 .authenticate()  提供了用户认证,即验证用户名以及密码是否正确,一般需要username ...

  7. JSch基本使用

    JSch基本使用 JSch 是SSH2的一个纯Java实现.它允许你连接到一个sshd 服务器,使用端口转发,X11转发,文件传输等等.你可以将它的功能集成到你自己的 程序中.同时该项目也提供一个J2 ...

  8. 洗碗机耗材:finish 亮碟 产品的选购

    转发&补充两点 1.亮碟在国内销售的洗涤块是最低端的Classic,二合一产品(理论上必须配合软水盐和亮碟剂).国外很早就淘汰掉Classic级的洗涤块了,当前最低端的是Advanced(四合 ...

  9. mysql 优化(2)

    --cfq,deadline,noop--radi10,xfs,ext4--innodb_flush_log_at_trx_commit=0/1/2--sys_binlog=1/n CPU的利用特点• ...

  10. 【BZOJ】1833: [ZJOI2010] count 数字计数(数位dp)

    题目 传送门:QWQ 分析 蒟蒻不会数位dp,又是现学的 用$ dp[i][j][k] $ 表示表示长度为i开头j的所有数字中k的个数 然后预处理出这个数组,再计算答案 代码 #include < ...