Android TV item 选中 放大,加边框
来源:互联网 发布:json date 格式化注解 编辑:程序博客网 时间:2024/06/07 06:13
Android Tv 的交互是通过遥控器来进行的,焦点移动是用户操作后的直观感受。如何让用户直观的操控Tv是本文的重点介绍内容。
1. Tv开发一般都会有自定义的Launcher,launcher中显示媒体资源数据。类似下图
每个item选中后会有个边框,并且会变大。下面将如何实现这个效果。
放大效果
首先item的布局,以LinearLayout为例,我们要的效果是当LinearLayout或者Imageview 获取焦点时, LinearLayout放大,当焦点移动到其他item时,此item丢失焦点,恢复原来的大小。所以我们自定义LinearLayout。
public class CustomLinearLayout extends LinearLayout implements View.OnFocusChangeListener, CustomViewInterface, View.OnHoverListener { CustomFocusedChanged focusedChanged; public CustomLinearLayout(Context context) { super(context); init(); } public CustomLinearLayout(Context context, @Nullable AttributeSet attrs) { super(context, attrs); init(); } public CustomLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(); } public CustomLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); init(); } public void setFocusedChanged(CustomFocusedChanged focusedChanged) { this.focusedChanged = focusedChanged; } @Override public void init() { this.setOnFocusChangeListener(this); this.setOnHoverListener(this); } @Override public void onFocusChange(View v, boolean hasFocus) { if (focusedChanged != null) { focusedChanged.onFocusChange(v, hasFocus);//外部接口调用 } DisplayUtil.setViewAnimator(v, hasFocus);//放大缩小动画 } //鼠标事件处理 @Override public boolean onHover(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_HOVER_ENTER) { DisplayUtil.setViewAnimator(v, true); } else if (event.getAction() == MotionEvent.ACTION_HOVER_EXIT) { DisplayUtil.setViewAnimator(v, false); } return false; }}
接口介绍
public interface CustomViewInterface { void init(); void setFocusedChanged(CustomFocusedChanged focusedChanged);}
此接口作用是因为我们的自定义控件获取焦点,当外部需要监听其焦点变化时,若再调用View.OnFocusChangeListener接口会覆盖掉我们自定义控件中的监听,所有再写一个接口供外部调用。
View.OnHoverListener接口未监听鼠标接口
实现onHover 方法
@Override public boolean onHover(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_HOVER_ENTER) { //鼠标进入控件范围 } else if (event.getAction() == MotionEvent.ACTION_HOVER_EXIT) { //鼠标离开控件 } return false; }
放大动画
public static final float ZOOM_SCALE = 1.05f;private static final float ORIGIN_SCALE = 1.0f; public static void setViewAnimator(View v, boolean focus) { setViewAnimator(v, focus, ZOOM_SCALE); } public static void setViewAnimator(View v, boolean focus, float... params) { AnimatorSet animatorSet = new AnimatorSet();//组合动画 ObjectAnimator scaleX; ObjectAnimator scaleY; if (focus) { scaleX = ObjectAnimator.ofFloat(v, "scaleX", ORIGIN_SCALE, params[0]); scaleY = ObjectAnimator.ofFloat(v, "scaleY", ORIGIN_SCALE, params[0]); } else { scaleX = ObjectAnimator.ofFloat(v, "scaleX", params[0], ORIGIN_SCALE); scaleY = ObjectAnimator.ofFloat(v, "scaleY", params[0], ORIGIN_SCALE); } if (params.length > 1) { v.setPivotX(params[1]); v.setPivotY(params[2]); } animatorSet.setDuration(300); animatorSet.setInterpolator(new DecelerateInterpolator()); animatorSet.play(scaleX).with(scaleY);//两个动画同时开始 animatorSet.start(); }
圆角效果
重点类:RoundDrawable,ColorStateList
public class RoundLinearLayout extends LinearLayout{ private ColorStateList mSolidColor; private int mCornerRadius; public RoundLinearLayout(Context context) { super(context); } public RoundLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } public RoundLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } public RoundLinearLayout(Context context, @Nullable AttributeSet attrs) { super(context, attrs); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundButton); float pressedRatio = a.getFloat(R.styleable.RoundButton_btnPressedRatio, 0.80f); mCornerRadius = a.getLayoutDimension(R.styleable.RoundButton_btnCornerRadius, getResources().getDimensionPixelSize(R.dimen.radius_default)); mSolidColor = a.getColorStateList(R.styleable.RoundButton_btnSolidColor); int strokeColor = a.getColor(R.styleable.RoundButton_btnStrokeColor, Color.GRAY); int strokeWidth = a.getDimensionPixelSize(R.styleable.RoundButton_btnStrokeWidth, 0); int strokeDashWidth = a.getDimensionPixelSize(R.styleable.RoundButton_btnStrokeDashWidth, 0); int strokeDashGap = a.getDimensionPixelSize(R.styleable.RoundButton_btnStrokeDashGap, 0); a.recycle(); RoundDrawable rd = new RoundDrawable(mCornerRadius == -1); rd.setCornerRadius(mCornerRadius == -1 ? 0 : mCornerRadius); rd.setStroke(strokeWidth, strokeColor, strokeDashWidth, strokeDashGap); if (mSolidColor == null) { mSolidColor = ColorStateList.valueOf(Color.GRAY); } if (mSolidColor.isStateful()) { rd.setSolidColors(mSolidColor); } else if (pressedRatio > 0.0001f) { rd.setSolidColors(csl(mSolidColor.getDefaultColor(), pressedRatio)); } else { rd.setColor(mSolidColor.getDefaultColor()); } setBackground(rd); } public void setSolidColor(int color) { RoundDrawable rd = new RoundDrawable(mCornerRadius == -1); rd.setCornerRadius(mCornerRadius == -1 ? 0 : mCornerRadius); mSolidColor = ColorStateList.valueOf(color); if (mSolidColor.isStateful()) { rd.setSolidColors(mSolidColor); } else { rd.setColor(mSolidColor.getDefaultColor()); } setBackground(rd); } int darker(int color, float ratio) { color = (color >> 24) == 0 ? 0x22808080 : color; float[] hsv = new float[3]; Color.colorToHSV(color, hsv); hsv[2] *= ratio; return Color.HSVToColor(color >> 24, hsv); } ColorStateList csl(int normal, float ratio) { // int disabled = greyer(normal); int pressed = darker(normal, ratio); int[][] states = new int[][]{{android.R.attr.state_pressed}, {}}; int[] colors = new int[]{pressed, normal}; return new ColorStateList(states, colors); }
attrs文件
<declare-styleable name="RoundButton"> <!-- 背景色 --> <attr name="btnSolidColor" format="color"/> <!-- 边框色 --> <attr name="btnStrokeColor" format="color"/> <!-- 边框厚度 --> <attr name="btnStrokeWidth" format="dimension"/> <!-- 边框虚线长度 --> <attr name="btnStrokeDashWidth" format="dimension"/> <!-- 边框虚线间隙 --> <attr name="btnStrokeDashGap" format="dimension"/> <!-- 圆角半径,stadium 表示半径为 min(height,width) / 2--> <attr name="btnCornerRadius" format="dimension"> <enum name="stadium" value="-1"/> </attr> <attr name="btnPressedRatio" format="float"/> </declare-styleable>
设置边框
创建item_background_focus.xml
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"> <stroke android:width="@dimen/cibn_view_stroke_width" android:color="@color/item_stroke_focus_color"/> <corners android:bottomLeftRadius="@dimen/radius_default"//圆角与RoundLinearLayout中的角度一致 android:bottomRightRadius="@dimen/radius_default" android:topLeftRadius="@dimen/radius_default" android:topRightRadius="@dimen/radius_default"/> <padding android:bottom="@dimen/cibn_view_stroke_padding" android:left="@dimen/cibn_view_stroke_padding" android:right="@dimen/cibn_view_stroke_padding" android:top="@dimen/cibn_view_stroke_padding"/></shape>
创建item_background_normal.xml
<?xml version="1.0" encoding="utf-8"?><shape xmlns:android="http://schemas.android.com/apk/res/android"> <stroke android:width="@dimen/cibn_view_stroke_width" android:color="@color/item_stroke_color"/> <corners android:bottomLeftRadius="@dimen/radius_default" android:bottomRightRadius="@dimen/radius_default" android:topLeftRadius="@dimen/radius_default" android:topRightRadius="@dimen/radius_default"/> <padding android:bottom="@dimen/cibn_view_stroke_padding" android:left="@dimen/cibn_view_stroke_padding" android:right="@dimen/cibn_view_stroke_padding" android:top="@dimen/cibn_view_stroke_padding"/></shape>
创建item_sleclected.xml
<?xml version="1.0" encoding="utf-8"?><selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/item_background_focus" android:state_focused="true"/> <item android:drawable="@drawable/item_background_normal" android:state_focused="false"/></selector>
设置item的背景为item_sleclected.xml即可
将自定义的LinearLayout 继承RoundLinearLayout ,即为最终控件。将布局文件中的LinearLayout替换成我们的自定义LinearLayout即为最终效果。(前提是焦点问题要处理好,焦点处理需要注意的点后面会单独介绍)
- Android TV item 选中 放大,加边框
- Android RecyclerView item选中放大被遮挡问题
- android UI效果二: 给选中的图片加边框
- android GridView 在TV上解决item放大时候,被其他item遮挡,单纯使用bringToFront无法解决的问题
- 关于gridview多item选中放大问题。
- android 选中GridView 中 的item 时进行图片放大的操作
- android tv gridview焦点放大效果
- android tv gridview焦点放大效果
- CSS实现图片选中加边框效果
- Android ImageView 加边框
- Android 图片加边框
- Android图片加边框
- Android ImageView加边框
- android TextView加边框
- 仿蜜蜂视频TV实现gridview选中放大,并且放大时弹出底部说明
- Android TV 开发-listview(GridView)使用键盘获取焦点时,选中上次失去焦点时的item,而不是就近的item
- Android 选中Gridiew的item
- Android - ImageView 加边框 实例
- 夜灵的Html笔记Day10——浏览器兼容性、复杂选择器
- 代码中遇到的问题
- [图像]HOG特征
- 大数据HBase_04_01
- 2017 ACM-ICPC 亚洲区(乌鲁木齐赛区)网络赛J
- Android TV item 选中 放大,加边框
- 栈和堆的区别
- java web(一)hmtl
- myeclipse总是加载项目building workspace过久
- ajax的同步异步
- Spring内置任务调度实现添加、取消、重置
- gradle 创建多模块工程
- PCA algorithm原理及使用
- CrashHandler实现UncaughtExceptionHandler拦截android异常