1. 程式人生 > >一步一步學習Android TV/盒子開發(三)

一步一步學習Android TV/盒子開發(三)

本文主要說的就是在TV開發中常遇到的問題總結

焦點丟失問題

在使用ListView、GridView及RecyclerView時有時會出現,這時需要在xml中,新增

android:descendantFocusability="afterDescendants"
  • 1
  • 2

這裡會有三種方式分別為

  • beforeDescendants:viewgroup會優先其子類控制元件而獲取到焦點

  • afterDescendants:viewgroup只有當其子類控制元件不需要獲取焦點時才獲取焦點

  • blocksDescendants:viewgroup會覆蓋子類控制元件而直接獲得焦點

在使用自定義組合控制元件是可以用程式碼設定,如下

setDescendantFocusability(FOCUS_BLOCK_DESCENDANTS);
  • 1
  • 2

控制元件呼叫bringToFront失效,導致焦點錯亂問題

原始碼中:

  • View

    public void bringToFront() {
        if (mParent != null) {
            mParent.bringChildToFront(this); // 是呼叫父佈局的 bringChildToFront
        }
    }
    
  • ViewGroup

  • 所以可以將你要置頂的子控制元件和最後一個要繪製的控制元件交換位置, 因為最後繪製的子控制元件是在最上面的。

    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)。