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这个控件,瞬间爱不释手,做东西的主 ...
随机推荐
- 亚马逊MWS开发套路演示
MWS是商城网络服务的缩写,具体介绍看这里http://docs.developer.amazonservices.com/zh_CN/dev_guide/DG_IfNew.html.MWS就是一组A ...
- DeepLearning4J 环境搭建【转】
深度学习Deeplearning4j eclipse 开发环境搭建 eclipse设置deeplearning4j开发环境:手动添加jar包 https://deeplearning4j.org/cn ...
- Unit02: JSON 、 使用JSON实现数据交换 、 jQuery对AJAX的支持,编码问题
Unit02: JSON . 使用JSON实现数据交换 . jQuery对AJAX的支持 1. 编码问题 (1)发送get请求 为什么会产生乱码? ie浏览器提供的ajax对象,对中文会使用gbk来编 ...
- 在Google的GKE上创建支持Internal Load Balancer的Service
在Google的Kubernetes Engine上发布service,可以采用除On-Promise相同的Cluster IP和NodePort两种方式外,还可以创建LoadBalaner的Serv ...
- 谈谈对zynq的浅显理解
zynq并不能说是一个嵌入arm核的FPGA.从它的启动过程就可以发现,绝对是arm主导的,所以称它为以高性能FPGA为外设的双核arm或许更为合适.以下是优势: 第一个:开发环境的大集成.从hls到 ...
- Redis:目录
ylbtech-Redis:目录 1.返回顶部 2.返回顶部 3.返回顶部 4.返回顶部 5.返回顶部 6.返回顶部 7.返回顶部 8.返回顶部 9.返回顶部 ...
- (转)CentOS 7安装Zabbix 3.4
(转)Zabbix 3.4 支持Centos 7.貌似不支持6.9. 更多详细内容请参考官方说明文档,详细的安装要求不贴出来了. https://www.zabbix.com/documentatio ...
- 使用DOSGi在OSGi环境下发布Web Services
前言 Apache CXF是一个开源的服务框架项目,而Distributed OSGi子项目提供了基于OSGi远程服务规范的分布式组件实现.它使用Web Services,HTTP上的SOAP手段实现 ...
- [置顶]
ubuntu版本很老,apt-get update更新失败时(W: Failed to fetch ...)------如何创建新的sources.list
在说这个解决方案之前,我先说下,目前遇到的问题: 我使用 sudo apt-get update 之后,更新失败.具体原因如下: W: Failed to fetch http://cn.archiv ...
- 【POJ】2373 Dividing the Path(单调队列优化dp)
题目 传送门:QWQ 分析 听说是水题,但还是没想出来. $ dp[i] $为$ [1,i] $的需要的喷头数量. 那么$ dp[i]=min(dp[j])+1 $其中$ j<i $ 这是个$ ...