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这个控件,瞬间爱不释手,做东西的主 ...
随机推荐
- error while loading shared libraries: libaio.so.1: cannot open shared object file: No such file or directory
编译出现如下错误: error while loading shared libraries: libaio.so.1: cannot open shared object file: No such ...
- 百度地图api使用,简单搜索+经纬度定位+自定义消息窗口
<html> <head> <meta http-equiv="Content-Type" content="text/html; char ...
- Windows远程桌面连接CentOS 7
1. 安装tigervnc-server yum install tigervnc-server 2. 设置vncserver服务器 将默认提供的文件复制到/etc/systemd/system,命令 ...
- Java 中 wait, notify 和 notifyAll的正确使用 – 以生产者消费者模型为例
如何使用Wait 尽管关于wait和notify的概念很基础,它们也都是Object类的函数,但用它们来写代码却并不简单.如果你在面试中让应聘者来手写代码,用wait和notify解决生产者消费者问题 ...
- PHP中的traits简单理解
Traits可以理解为一组能被不同的类都能调用到的方法集合,但Traits不是类!不能被实例化.先来例子看下语法: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1 ...
- IntelliJ Idea使用scalatest
背景:作为测试,开发写什么,测试自然就要测什么了,so = = 无scala基础,人较笨,折腾了两天才把环境弄好,如下: 一 IntelliJ Idea下载安装 这个真心是最简单的了 https:// ...
- linux中find工具
find 由于find具有强大的功能,所以它的选项也很多,其中大部分选项都值得我们花时间来了解一下.即使系统中含有网络文件系统( NFS),find命令在该文件系统中同样有效,只要你具有相应的权限. ...
- C#做的在线升级小程序
转自原文C#做的在线升级小程序 日前收到一个小任务,要做一个通用的在线升级程序.更新的内容包括一些dll或exe或.配置文件.升级的大致流程是这样的,从服务器获取一个更新的配置文件,经过核对后如有新的 ...
- RTTI(一) 枚举
SetEnumProp void __fastcall TForm2::Button1Click(TObject *Sender) { //Getting the current color of t ...
- Maven父级pom.xml配置文件
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...