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这个控件,瞬间爱不释手,做东西的主 ...
随机推荐
- 推动FPGA发展箭在弦上,国内厂商须走差异化之路
7月25日,由中国电子报与深圳投资推广署共同举办的“第六届(2018)中国FPGA产业发展论坛”在深圳召开. 作为四大通用集成电路芯片之一,FPGA(现场可编程门阵列)的重要性与CPU.存储器.DSP ...
- 阻塞队列之四:ArrayBlockingQueue
一.ArrayBlockingQueue简介 一个由循环数组支持的有界阻塞队列.它的本质是一个基于数组的BlockingQueue的实现. 它的容纳大小是固定的.此队列按 FIFO(先进先出)原则对元 ...
- POJ 3276 Face The Right Way(反转)
Face The Right Way Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 6038 Accepted: 2 ...
- 安装SQL Servre2000时提示“command line option syntax error! type command /? for help”
问题: 当程序正在安装ms数据访问组件时,弹出错误提示框:command line option syntax error,type command/? for help,点击确定继续:到了程序正在安 ...
- 运维平台cmdb开发-day1
序读项目由来 终极目标,运维平台.自动化.装机,监控,安装软件,部署基础服务,资产管理,之前是excel,现在是客户端自动获取,变更记录 后台管理 api 采集资产 四种模式agent 定时,每天执行 ...
- C/C++程序内存情况
一个由C/C++编译的程序占用的内存分为以下几个部分 1.栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构中的栈. 2.堆区(heap) — 一 ...
- node的超时timeout
如果在指定的时间内服务器没有做出响应(可能是网络间连接出现问题,也可能是因为服务器故障或网络防火墙阻止了客户端与服务器的连接),则响应超时,同时触发http.ServerResponse对象的time ...
- JAVA访问控制变量、类变量、类方法
1.私有:同类中 2.默认:同包中的类 3.保护:同包中的类 子类中(继承性) 4.公有:无范围 创建子类并覆盖方法时,必须考虑原来方法的访问控制: 作为通用的规则,覆盖方法是,新方法的访问控制不能 ...
- Cisco动态路由 OSPF协议
OSPF描述: 组播扩展OSPF 锁定 同义词 ospf一般指组播扩展OSPF 本词条由“科普中国”百科科学词条编写与应用工作项目 审核 . OSPF(Open Shortest Path Firs ...
- 关于PHP导出excel文件名乱码的问题
关于PHP导出excel文件名乱码的问题 对于中文的文件名使用,urlencode即可避免此问题 urlencode() 申请的urlencode()