本文主要说的就是在TV开发中常遇到的问题总结
焦点丢失问题
在使用ListView、GridView及RecyclerView时有时会出现,这时需要在xml中,添加
android:descendantFocusability="afterDescendants"
这里会有三种方式分别为
beforeDescendants:viewgroup会优先其子类控件而获取到焦点
afterDescendants:viewgroup只有当其子类控件不需要获取焦点时才获取焦点
blocksDescendants:viewgroup会覆盖子类控件而直接获得焦点
在使用自定义组合控件是可以用代码设置,如下
setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS);
控件调用bringToFront失效,导致焦点错乱问题
源码中:
-
View
public void bringToFront() { if (mParent != null) { mParent.bringChildToFront(this); // 是调用父布局的 bringChildToFront } }
-
ViewGroup
@Override public void bringChildToFront(View child) { final int index = indexOfChild(child); if (index >= 0) { removeFromArray(index); // 删除子控件数组位置. addInArray(child, mChildrenCount); // 添加子控件到队尾. child.mParent = this; requestLayout(); invalidate(); } }
-
所以可以将你要置顶的子控件和最后一个要绘制的控件交换位置, 因为最后绘制的子控件是在最上面的。
setChildrenDrawingOrderEnabled(true) @Override protected int getChildDrawingOrder(int childCount, int i) { if (position != -1) { if (i == childCount - 1) return position; if (i == position) return childCount - 1; } return i; }
-
ViewUtil
public class ViewUtil { private final ViewGroup viewGroup; private int position; public ViewUtil(ViewGroup group) { this.viewGroup = group; } public void bringChildToFront(ViewGroup vg, View child) { position = vg.indexOfChild(child); if (position != -1) { vg.postInvalidate(); } } public void bringChildToFront(View child) { if (viewGroup == null) { return; } position = viewGroup.indexOfChild(child); if (position != -1) { viewGroup.postInvalidate(); } } public int getChildDrawingOrder(int childCount, int i) { if (position != -1) { if (i == childCount - 1) return position; if (i == position) return childCount - 1; } return i; } }
-
在Android5.0以后可以通设置控件的Z坐标达到相同的效果
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { ViewCompat.setElevation(view, 1); } else { if (view.getParent() instanceof BringChildLinearLayout) { BringChildLinearLayout layout = (BringChildLinearLayout) view.getParent(); layout.bringChildToFront(view); } }
跑马灯失效
- 自定义TextView实现跑马灯时,设置单行时用“maxLines=1”不生效,应该使用“singleLine=true”(过期的API)。