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这个控件,瞬间爱不释手,做东西的主 ...
随机推荐
- textArea中的maxlength是无效的 解决办法
-------------------------------------------------------------------------------------- <s:texta ...
- jeecg中List页面标签的用法
1.t:datagrid的常用属性 1. <t:datagrid name="jeecgDemoList" checkbox="true" sortNam ...
- ACM-世界岛旅行
[问题描述] 某旅游公司组团去迪拜世界岛旅游.世界岛由n个岛屿组成,岛屿序号为1-n,这些岛屿都直接或间接相连.岛屿之间用桥梁连接.现从1号岛屿开始游览,并约定按如下方式游览: 1) 每游览完一个岛屿 ...
- 全局获取Context
1.定制一个Application类,管理全局的状态信息 public class MyApplication extends Application{ private static Context ...
- Linux命令-chmod、chown和chgrp
Linux系统中的每个文件和目录都有访问许可权限,用它来确定谁可以通过何种方式对文件和目录进行访问和操作. 文件或目录的访问权限分为只读,只写和可执行三种.以文件为例,只读权限表示只允许读其内容,而禁 ...
- 非常漂亮js动态球型云标签特效代码
<%@ page contentType="text/html;charset=UTF-8" language="java" import="j ...
- 第十二章 Ganglia监控Hadoop及Hbase集群性能(安装配置)
1 Ganglia简介 Ganglia 是 UC Berkeley 发起的一个开源监视项目,设计用于测量数以千计的节点.每台计算机都运行一个收集和发送度量数据(如处理器速度.内存使用量等)的名为 gm ...
- 【BZOJ】2819: Nim(树链剖分 / lca+dfs序+树状数组)
题目 传送门:QWQ 分析 先敲了个树链剖分,发现无法AC(其实是自己弱,懒得debug.手写栈) 然后去学了学正解 核心挺好理解的,$ query(a) $是$ a $到根的异或和. 答案就是$ l ...
- 【洛谷】P3908 异或之和(异或)
题目描述 求1 \bigoplus 2 \bigoplus\cdots\bigoplus N1⨁2⨁⋯⨁N 的值. A \bigoplus BA⨁B 即AA , BB 按位异或. 输入输出格式 输入格 ...
- GroupVarint
folly/GroupVarint.h folly/GroupVarint.h is an implementation of variable-length encoding for 32- and ...