天天看點

Android TV自定義處理焦點控件

Android stuido有android tv項目模闆,有一套規則,如果想開發TV版項目可以按照那個模闆來,不過那個模闆定制性太強。tv版app和其他app有一點不同,就是用遙控器進行操作,是以要想按照自己需求來開發,就要處理好焦點事件。

其實也不複雜,隻要繼承現有的控件,在onFocusChanged事件中,對自己的需求進行定制就可以了。提供幾個例子:

1.顯示圖檔的控件,預設加載預設圖檔,當獲得焦點以後,切換選中圖檔,失去焦點,切換預設圖檔

public class FocusImageView extends ImageButton
{
    private int defaultImageResources = -;
    private int focusImageResources = -;

    public FocusImageView(Context context)
    {
        super(context);
    }

    public FocusImageView(Context context, AttributeSet attrs)
    {
        this(context, attrs, );
    }

    public FocusImageView(Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
        setAttributeSet(attrs);
    }

    @Override
    protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect)
    {
        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
        if (gainFocus)
        {
            if (focusImageResources != -)
            {
                setBackgroundResource(focusImageResources);
            }
        }
        else
        {
            if (defaultImageResources != -)
            {
                setBackgroundResource(defaultImageResources);
            }
        }
    }

    private void setAttributeSet(AttributeSet attrs)
    {
        if (attrs != null)
        {
            TypedArray typeArray = getContext().obtainStyledAttributes(attrs, R.styleable.FocusImageView);
            defaultImageResources = typeArray.getResourceId(R.styleable.FocusImageView_defaultImageResources, -);
            focusImageResources = typeArray.getResourceId(R.styleable.FocusImageView_focusImageResources, -);
            if (defaultImageResources != -)
            {
                setBackgroundResource(defaultImageResources);
            }
        }
    }
}
           

attrs.xml

<resources>

    <declare-styleable name="FocusImageView">
        <attr name="defaultImageResources" format="integer" />
        <attr name="focusImageResources" format="integer" />
    </declare-styleable>

</resources>
           

布局檔案引用:

<項目的包名.widget.focusview.FocusImageView
                    android:id="@+id/iv_wulianwang"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    app:defaultImageResources="@mipmap/wulianwangdefault"
                    app:focusImageResources="@mipmap/wulianwangselected">
</項目的包名.widget.focusview.FocusImageView>
           

當然,如果隻是在擷取焦點和失去焦點,切換圖檔,可以定義selector,在drawable下,定義一個selector

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@mipmap/bingliselected" android:state_focused="true" />
    <item android:drawable="@mipmap/binglidefault" />
</selector>
           

然後在布局中調用

<LinearLayout
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_margin="6dp"
                    android:focusable="true"
                    android:background="@drawable/focus_selector">
           

2.一個布局,内部控件獲得焦點,可以放大,失去焦點,内部控件可以縮小:

public class FocusRelativeLayout extends RelativeLayout {

    private Animation scaleSmallAnimation;
    private Animation scaleBigAnimation;

    public FocusRelativeLayout(Context context) {
        super(context);
    }

    public FocusRelativeLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public FocusRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
        super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);
        if (gainFocus) {
            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);
    }
}
           

anim_scale_big.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true"
    android:shareInterpolator="false">
    <scale
        android:duration="350"
        android:fromXScale="1.0"
        android:fromYScale="1.0"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:pivotX="50.0%"
        android:pivotY="50.0%"
        android:repeatCount="0"
        android:toXScale="1.08"
        android:toYScale="1.08" />
</set>
           

anim_scale_small.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true"
    android:shareInterpolator="false">
    <scale
        android:duration="350"
        android:fromXScale="1.08"
        android:fromYScale="1.08"
        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>
           

布局檔案引用:

<包名.view.FocusRelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                                                     android:layout_width="wrap_content"
                                                     android:layout_height="wrap_content"
                                                     android:background="#424242"
                                                     android:clipChildren="true"
                                                     android:focusable="true">

        <ImageView
                android:layout_width="100dp"
                android:layout_height="100dp"
                android:scaleType="fitXY"
                android:src="@drawable/pic2"
                android:layout_margin="5dp"/>
    </包名.view.FocusRelativeLayout>
           

3.進入界面,讓某個控件擷取焦點

根據需求,可能對進入界面,首先選中哪個控件有需求,可以在布局檔案裡邊,使用

<requestFocus/>屬性

<包名.widget.focusview.FocusImageView
                    android:id="@+id/iv_bingli"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    app:defaultImageResources="@mipmap/binglidefault"
                    app:focusImageResources="@mipmap/bingliselected"
            >
                <requestFocus></requestFocus>
            </包名.widget.focusview.FocusImageView>
           

繼續閱讀