Android TV焦点框动画效果
2015-12-23 17:33
627 查看
背景意义
对于TV端来说,各种Android事件的处理,依赖于遥控操作,不像移动终端可以通过Touch主观感觉焦点存在位置,TV焦点需要通过图像显示出来.
因此焦点框显示效果非常影响用户体验,一般焦点效果常见的是控件背景加高亮框,或通过触发事件切换背景,亦或伸缩控件大小.实际上,我们可以实现具有动画效果的焦点框.
实现的动画效果为:使用平移动画绘制焦点框移动轨迹,同时焦点框随着控件形状动态改变.动画最终状态是,焦点框从失去焦点的位置移动到获得焦点的位置,控件放大,焦点框尺寸最后变为放大后的控件尺寸.
控件自身获得或失去焦点伸缩效果实现函数
最终效果
http://v.youku.com/v_show/id_XMTQyMTc0ODgxNg==.html
对于TV端来说,各种Android事件的处理,依赖于遥控操作,不像移动终端可以通过Touch主观感觉焦点存在位置,TV焦点需要通过图像显示出来.
因此焦点框显示效果非常影响用户体验,一般焦点效果常见的是控件背景加高亮框,或通过触发事件切换背景,亦或伸缩控件大小.实际上,我们可以实现具有动画效果的焦点框.
实现的动画效果为:使用平移动画绘制焦点框移动轨迹,同时焦点框随着控件形状动态改变.动画最终状态是,焦点框从失去焦点的位置移动到获得焦点的位置,控件放大,焦点框尺寸最后变为放大后的控件尺寸.
控件自身获得或失去焦点伸缩效果实现函数
private void showOnFocusAnimation(View v, float scale) { animEffect.setAttributs(1.0f, scale, 1.0f, scale, 100); Animation anim = animEffect.createAnimation(); v.startAnimation(anim); v.bringToFront(); } private void showLoseFocusAnimation(View v, float scale) { animEffect.setAttributs(scale, 1.0f, scale, 1.0f, 100); Animation anim = animEffect.createAnimation(); v.startAnimation(anim); }自定义焦点框控件类
package com.gotech.tv.launcher.view; import com.gotech.tv.launcher.util.Constant; import com.gotech.tv.launcher.util.DensityUtil; import android.content.Context; import android.graphics.Rect; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; import android.view.animation.DecelerateInterpolator; public class FlyBorderView extends View { private View mFocusView; private View mSelectView; private boolean isTvScreen = false; public FlyBorderView(Context context) { super(context, null, 0); init(context); } public FlyBorderView(Context context, AttributeSet attrs) { super(context, attrs, 0); init(context); } public FlyBorderView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } private void init(Context context) { } public boolean isTvScreen() { return isTvScreen; } public void setTvScreen(boolean isTvScreen) { this.isTvScreen = isTvScreen; invalidate(); } /** * 设置焦点框的移动. */ public void setFocusView(View view, float scale) { if (mFocusView != view) { mFocusView = view; runTranslateAnimation(mFocusView, scale, scale); } } public void setSelectView(View view) { if (mSelectView != view) { mSelectView = view; runTranslateAnimation(mSelectView); } } private void runTranslateAnimation(View toView) { Rect fromRect = findLocationWithView(this); Rect toRect = findLocationWithView(toView); int x = toRect.left - fromRect.left; int y = toRect.top - fromRect.top; int deltaX = (toView.getWidth() - this.getWidth()) / 2; int deltaY = (toView.getHeight() - this.getHeight()) / 2; // tv if (isTvScreen) { x = DensityUtil.dip2px(this.getContext(), x + deltaX); y = DensityUtil.dip2px(this.getContext(), y + deltaY); } else { x = x + deltaX; y = y + deltaY; } flyWhiteBorder(x, y); } private void flyWhiteBorder(float x, float y) { animate().translationX(x).translationY(y).setDuration(Constant.TRAN_DUR_ANIM).setInterpolator(new DecelerateInterpolator()).start(); } public void runTranslateAnimation(View toView, float scaleX, float scaleY) { Rect fromRect = findLocationWithView(this); Rect toRect = findLocationWithView(toView); int x = toRect.left - fromRect.left; int y = toRect.top - fromRect.top; int deltaX = (toView.getWidth() - this.getWidth()) / 2; int deltaY = (toView.getHeight() - this.getHeight()) / 2; // tv if (isTvScreen) { x = DensityUtil.dip2px(this.getContext(), x + deltaX); y = DensityUtil.dip2px(this.getContext(), y + deltaY); } else { x = x + deltaX; y = y + deltaY; } float toWidth = toView.getWidth() * scaleX; float toHeight = toView.getHeight() * scaleY; int width = (int) (toWidth); int height = (int) (toHeight); flyWhiteBorder(width, height, x, y); } private void flyWhiteBorder(int width, int height, float x, float y) { int mWidth = this.getWidth(); int mHeight = this.getHeight(); float scaleX = (float) width / (float) mWidth; float scaleY = (float) height / (float) mHeight; animate().translationX(x).translationY(y).setDuration(Constant.TRAN_DUR_ANIM).scaleX(scaleX).scaleY(scaleY).setInterpolator(new DecelerateInterpolator()).start(); } public Rect findLocationWithView(View view) { ViewGroup root = (ViewGroup) this.getParent(); Rect rect = new Rect(); root.offsetDescendantRectToMyCoords(view, rect); return rect; } }XML布局文件
<?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"> ... <FrameLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@+id/homeTitle_bar"> <com.gotech.tv.launcher.view.MainLayout android:id="@+id/main_layout" android:layout_width="match_parent" android:layout_height="wrap_content"> ... </com.gotech.tv.launcher.view.MainLayout> <com.gotech.tv.launcher.view.FlyBorderView android:id="@+id/flyBorder_view" android:layout_width="@dimen/border_width" android:layout_height="@dimen/border_height" android:background="@drawable/item_highlight" android:visibility="invisible"/> </FrameLayout>控件事件监听
private void initView() { mFlyBorderView = (FlyBorderView) getParentView().findViewById(R.id.flyBorder_view); mMainLayout = (MainLayout) getParentView().findViewById(R.id.main_layout); for (int index = 0; index < mMainLayout.getChildCount(); index++) { mMainLayout.getChildAt(index).setOnFocusChangeListener(this); mMainLayout.getChildAt(index).setOnClickListener(this); } reflectImageView(); }控件事件处理
@Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { mFlyBorderView.setVisibility(View.VISIBLE); mFlyBorderView.setTvScreen(true); if (v.getId() == R.id.frame_tv) { mFlyBorderView.setFocusView(v, 1.15f); showOnFocusAnimation(v, 1.15f); } else { mFlyBorderView.setFocusView(v, 1.20f); showOnFocusAnimation(v, 1.20f); } } else { mFlyBorderView.setVisibility(View.INVISIBLE); if (v.getId() == R.id.frame_tv) { showLoseFocusAnimation(v, 1.15f); } else { showLoseFocusAnimation(v, 1.20f); } } }
最终效果
http://v.youku.com/v_show/id_XMTQyMTc0ODgxNg==.html
相关文章推荐
- android之PreferenceActivity使用详解
- android之TextView部分本文变颜色,并设置文本监听器
- android MTP
- android学习及一些技能
- 通过jni调用OpenCv跟直接调用android版openCv对图片进行简单的变换
- Android:Tricks to boost performance of list view
- android com.android.support:design库使用
- Android--ViewPager-Fragment
- Android开发笔记(二十五)assets目录下的文件读取
- android 事件分发
- Android Studio常用快捷键
- android渐变动画的两种实现
- 详解Android中处理崩溃异常
- android登陆按钮悬浮在软键盘上
- android混淆总结
- Android Tablayout使用示例及详解
- 3.Android之单选按钮RadioGroup和复选框Checkbox学习
- Android 4.4从图库选择图片并裁剪,由于系统版本不同导致Uri的bug的简单解决方式
- 关于android学习的个人理解
- Android布局调整