Android TV上的焦点切换效果
转载:http://blog.csdn.net/wzlas111/article/details/39741091
Android TV上的焦点凸显特效相信大家都看到过,那么我们就来实现它吧,首先上张效果图。
先说一下实现原理,主要通过重写RelativeLayout实现item,之后在其中加入scalanimation动画效果。刚开始处理时,还是发现了一些问题,比如item放大后会被其他item遮挡,如何添加选中边框等等,以及动画的实现等等。下面放上实现细节。
首先是item的代码:
- <view xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/item"
- android:layout_width="@dimen/home_channel_item_width"
- android:layout_height="@dimen/home_channel_item_height"
- class="com.eastelsoft.tv.widget.home.HomeItemContainer"
- android:clickable="true"
- android:focusable="true"
- android:focusableInTouchMode="true"
- android:clipChildren="false"
- android:clipToPadding="false" >
- <com.eastelsoft.tv.widget.ESImageView
- android:id="@+id/img"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:background="@drawable/holder_nor"
- android:duplicateParentState="true"
- android:scaleType="fitXY" />
- <!-- -->
- <com.eastelsoft.tv.widget.ESImageView
- android:id="@+id/hover"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:contentDescription="@string/desc"
- android:duplicateParentState="true"
- android:scaleType="fitXY"
- android:src="@drawable/sl_image_home_navigator" />
- <TextView
- android:id="@+id/text"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentBottom="true"
- android:layout_marginBottom="@dimen/home_item_text_margin"
- android:layout_marginLeft="@dimen/home_item_text_margin"
- android:layout_marginRight="@dimen/home_item_text_margin"
- android:ellipsize="marquee"
- android:gravity="bottom|right|center"
- android:includeFontPadding="false"
- android:marqueeRepeatLimit="5"
- android:maxWidth="@dimen/px310"
- android:shadowColor="#88333333"
- android:shadowDx="2.0"
- android:shadowDy="2.0"
- android:shadowRadius="2.0"
- android:singleLine="true"
- android:textColor="#ffffffff" />
- </view>
这里定义了一个自定义view,代码在后面放上,每个item里添加了一个img,用于放置内容图片,一个hover,用于显示选中的边框,以及一个text,显示一些文字说明。
hover的src是一个selector drawable,当未focus时,它的背景是tansparent,当focus,放入外框图片。
自定义的HomeItemContainer 代码:
- public class HomeItemContainer extends RelativeLayout {
- private Rect mBound;
- private Drawable mDrawable;
- private Rect mRect;
- private Animation scaleSmallAnimation;
- private Animation scaleBigAnimation;
- public HomeItemContainer(Context context) {
- super(context);
- init();
- }
- public HomeItemContainer(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- init();
- }
- public HomeItemContainer(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
- protected void init() {
- setWillNotDraw(false);
- mRect = new Rect();
- mBound = new Rect();
- mDrawable = getResources().getDrawable(R.drawable.poster_shadow_4);//nav_focused_2,poster_shadow_4
- setChildrenDrawingOrderEnabled(true);
- }
- @Override
- protected void onAttachedToWindow() {
- super.onAttachedToWindow();
- }
- @Override
- public void draw(Canvas canvas) {
- super.draw(canvas);
- }
- @Override
- protected void onDraw(Canvas canvas) {
- if (hasFocus()) {
- System.out.println("HomeItemContainer focus : true ");
- super.getDrawingRect(mRect);
- mBound.set(-39+mRect.left, -39+mRect.top, 39+mRect.right, 39+mRect.bottom);
- mDrawable.setBounds(mBound);
- canvas.save();
- mDrawable.draw(canvas);
- canvas.restore();
- }
- super.onDraw(canvas);
- }
- @Override
- protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
- super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
- if (gainFocus) {
- bringToFront();
- getRootView().requestLayout();
- getRootView().invalidate();
- zoomOut();
- } else {
- zoomIn();
- }
- }
- private void zoomIn() {
- if (scaleSmallAnimation == null) {
- scaleSmallAnimation = AnimationUtils.loadAnimation(getContext(), R.anim.anim_scale_small);
- }
- startAnimation(scaleSmallAnimation);
- }
- private void zoomOut() {
- if (scaleBigAnimation == null) {
- scaleBigAnimation = AnimationUtils.loadAnimation(getContext(), R.anim.anim_scale_big);
- }
- startAnimation(scaleBigAnimation);
- }
- }
注意onFocusChanged方法,为防止item被其他item遮挡,先调用bringToFront方法,使此item处于最上层,之后调用父view的方法进行重新绘制,其实注意一点,item必须处于同一父view中,否则requestLayout和invalidate可能会不起作用,只适用于RelativeLayout布局,经测试LinearLayout不适用。
顺便放上一个scaleanimation缩小的效果代码:
- <?xml version="1.0" encoding="utf-8"?>
- <set xmlns:android="http://schemas.android.com/apk/res/android"
- android:fillAfter="false"
- android:fillBefore="true"
- android:shareInterpolator="false" >
- <scale
- android:duration="200"
- android:fromXScale="1.1"
- android:fromYScale="1.1"
- android:interpolator="@android:anim/accelerate_decelerate_interpolator"
- android:pivotX="50.0%"
- android:pivotY="50.0%"
- android:repeatCount="0"
- android:toXScale="1.0"
- android:toYScale="1.0" />
- </set>
里面的属性就不详细介绍了,有兴趣的可以自己谷歌。
最后放上item的父view:
- <?xml version="1.0" encoding="utf-8"?>
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="horizontal"
- android:padding="10dp"
- android:clipChildren="false"
- android:clipToPadding="false" >
- <include
- android:id="@+id/channel_0"
- android:layout_width="@dimen/home_channel_item_width"
- android:layout_height="@dimen/home_channel_item_height"
- layout="@layout/home_page_channel_item"
- android:layout_alignParentLeft="true"
- android:layout_alignParentTop="true"
- android:layout_margin="3dp" />
- <include
- android:id="@+id/channel_1"
- android:layout_width="@dimen/home_channel_item_width"
- android:layout_height="@dimen/home_channel_item_height"
- layout="@layout/home_page_channel_item"
- android:layout_below="@id/channel_0"
- android:layout_alignLeft="@id/channel_0" />
- <include
- android:id="@+id/channel_2"
- android:layout_width="@dimen/home_channel_item_width"
- android:layout_height="@dimen/home_channel_item_height"
- layout="@layout/home_page_channel_item"
- android:layout_toRightOf="@id/channel_0"
- android:layout_alignTop="@id/channel_0"
- android:layout_marginRight="3dp"
- android:layout_marginBottom="3dp"/>
- <include
- android:id="@+id/channel_3"
- android:layout_width="@dimen/home_channel_item_width"
- android:layout_height="@dimen/home_channel_item_height"
- layout="@layout/home_page_channel_item"
- android:layout_alignLeft="@id/channel_2"
- android:layout_below="@id/channel_2"/>
- <include
- android:id="@+id/channel_4"
- android:layout_width="@dimen/home_channel_item_width"
- android:layout_height="@dimen/home_channel_item_height"
- layout="@layout/home_page_channel_item"
- android:layout_toRightOf="@id/channel_2"
- android:layout_alignTop="@id/channel_2"
- android:layout_marginRight="3dp"
- android:layout_marginBottom="3dp"/>
- <include
- android:id="@+id/channel_5"
- android:layout_width="@dimen/home_channel_item_width"
- android:layout_height="@dimen/home_channel_item_height"
- layout="@layout/home_page_channel_item"
- android:layout_alignLeft="@id/channel_4"
- android:layout_below="@id/channel_4"/>
- <include
- android:id="@+id/channel_6"
- android:layout_width="@dimen/home_channel_item_width"
- android:layout_height="@dimen/home_channel_item_height"
- layout="@layout/home_page_channel_item"
- android:layout_toRightOf="@id/channel_4"
- android:layout_alignTop="@id/channel_4"
- android:layout_marginRight="3dp"
- android:layout_marginBottom="3dp"/>
- <include
- android:id="@+id/channel_7"
- android:layout_width="@dimen/home_channel_item_width"
- android:layout_height="@dimen/home_channel_item_height"
- layout="@layout/home_page_channel_item"
- android:layout_alignLeft="@id/channel_6"
- android:layout_below="@id/channel_6"/>
- <include
- android:id="@+id/channel_8"
- android:layout_width="@dimen/home_channel_item_width"
- android:layout_height="@dimen/home_channel_item_height"
- layout="@layout/home_page_channel_item"
- android:layout_toRightOf="@id/channel_6"
- android:layout_alignTop="@id/channel_6"
- android:layout_marginRight="3dp"
- android:layout_marginBottom="3dp"/>
- <include
- android:id="@+id/channel_9"
- android:layout_width="@dimen/home_channel_item_width"
- android:layout_height="@dimen/home_channel_item_height"
- layout="@layout/home_page_channel_item"
- android:layout_alignLeft="@id/channel_8"
- android:layout_below="@id/channel_8"/>
- </RelativeLayout>
这里我定义了10个item,注意RelativeLayout的两个属性,clipChildren设置false,让children view可以超出自身所设置的大小,clipToPadding设置为false,让children view可以使用padding 的位置进行绘制,有了这2个属性,item就可以实现放大而不被遮挡了。
好了,焦点特效的教程就说到这里了,有问题可以在评论中反馈。
Android TV上的焦点切换效果的更多相关文章
- Android:给ViewPager添加切换效果
原文参照开发者官网:http://developer.android.com/training/animation/screen-slide.html#viewpager 以App的引导页为例: 首先 ...
- android TV选中时高亮凸显效果
链接: http://pan.baidu.com/s/1pLjAFQ7 密码: xb8g <ignore_js_op> 360手机助手截图0410_18_02_01.png (335.64 ...
- Android下Fragment的动画切换效果
效果图如下: 源码链接 : 请戳这里
- React-Native解决ListView 在Android手机上无吸顶效果
stickySectionHeadersEnabled={true} stickyHeaderIndices={[0]}
- Android实现程序前后台切换效果
本文演示如何在Android中实现程序前后台切换效果. 在介绍程序实现之前,我们先看下Android中Activities和Task的基础知识. 我们都知道,一个Activity 可以启动另一个Act ...
- Android TV listView焦点平滑移动
先上TV上效果图 Mark下思路: package com.test.ui; import java.lang.reflect.Method; import android.annotation.Su ...
- 两行代码搞定Android视图扩散切换效果
用最简单的方式来实现Android视图扩散切换效果. 一.概述 这两天时间动手撸了个视图扩散切换效果的控制器,API兼容至Android4.0,更方便我们在视图切换过程中有炫酷的过渡效果.本来是想实现 ...
- Android TV开发总结(五)TV上屏幕适配总结
前言:前面几篇总结一些TV上的小Sample,开源到GitHub:https://github.com/hejunlin2013/TVSample, 点击链接,可以持续关注.今天总结下TV上屏幕适配. ...
- Android 自定义 ViewPager 打造千变万化的图片切换效果
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/38026503 记得第一次见到ViewPager这个控件,瞬间爱不释手,做东西的主 ...
随机推荐
- docker怎么破?
为什么要装docker? 因为linux服务器不好用,很多操作不好进行,比如安装包没有管理员权限 docker可以访问本地显卡,比一般的virtual box 或者VMware都要好 怎么装docke ...
- 轻量级封装DbUtils&Mybatis之四MyBatis主键
MyBatis主键 不支持对象列表存储时对自增id字段的赋值(至少包括3.2.6和3.3.0版本),如果id不是采用底层DB自增主键赋值,不必考虑此问题 温馨提示:分布式DB环境下,DB主键一般会采用 ...
- 螺旋填数:读入两个整数m,n,输出一个m行n列的矩阵,这个矩阵是1~m*n这些自然数按照右、下、左、上螺旋填入的结果。
package Day8_06; /*读入两个整数m,n,输出一个m行n列的矩阵,这个矩阵是1~m*n这些自然数按照右.下.左.上螺旋填入的结果. * 例如读入数字4,5,则输出结果为: * 1 2 ...
- MySQL 库、表
1.库 1.库的基本操作 1.查看已有的库 show databases; 2.创建库(指定默认字符集) create database 库名 default charset=utf8; 3.查看创建 ...
- java实现二叉树demo
二叉树(BinaryTree)是n(n≥0)个结点的有限集,它或者是空集(n=0),或者由一个根结点及两棵互不相交的.分别称作这个根的左子树和右子树的二叉树组成. 这个定义是递归的.由于左.右子 ...
- django之设置分页
分页 Django提供了一些类实现管理数据分页,这些类位于django/core/paginator.py中 Paginator对象 Paginator(列表,int):返回分页对象,参数为列表数据, ...
- congst与指针
指向const的指针 //a pointer to const int;指针指向常量对象,相对本指针而言,不能指针指向的对象的常量,不能通过本指针修改常量对象指针,实际的对象不一定的常量 const指 ...
- Linux下编译、安装php
一.apache环境下php的安装步骤如下:[注意:编译安装php前,应先安装好apache,因为编译php时要用到apache的路径] 1. 在http://www.php.net/download ...
- .net Reactor之限指定设备使用
.net Reactor之license限指定设备使用 上一篇(https://www.cnblogs.com/s313139232/p/9908400.html)中记录了.net Reactor对d ...
- C# WinForm ProgressBar垂直显示进度和从右向左显示进度
1. 尝试将ProgressBar的RightToLeft属性设置为System.Windows.Forms.RightToLeft.Yes,同时将RightToLeftLayout属性设置为true ...