最近開始接觸TV端開發(fā),初轉(zhuǎn)入TV端纯赎,有好多不適應(yīng)。尤其是對(duì)焦點(diǎn)的處理南蹂,上篇文章對(duì)leanback的使用做了簡單的介紹犬金,并對(duì)Item獲取焦點(diǎn)后的高亮顯示進(jìn)行了處理。但是六剥,如果按照同樣的方法在非列表頁實(shí)現(xiàn)時(shí)晚顷,效果并不理想,并會(huì)出現(xiàn)難以控制等問題疗疟。于是该默,開始尋找新的實(shí)現(xiàn)方式。在網(wǎng)上找了好多實(shí)現(xiàn)方式秃嗜,均不是特別理想权均。最終找到了一篇比較滿意的文章,自己在此基礎(chǔ)上進(jìn)行了優(yōu)化改進(jìn)锅锨。Demo的截圖如下:
下面就詳細(xì)介紹一下實(shí)現(xiàn)流程吧叽赊。
(1)自定義View,實(shí)現(xiàn)獲取焦點(diǎn)時(shí)放大必搞,失去焦點(diǎn)時(shí)縮小必指,詳細(xì)代碼如下:
[java]view plaincopy
packagecn.chinaiptv.newaikan.view;
importandroid.content.Context;
importandroid.graphics.Canvas;
importandroid.graphics.Rect;
importandroid.graphics.drawable.Drawable;
importandroid.util.AttributeSet;
importandroid.view.animation.Animation;
importandroid.view.animation.AnimationUtils;
importandroid.widget.RelativeLayout;
importcn.chinaiptv.newaikan.R;
publicclassFocusRelativeLayoutextendsRelativeLayout?{
privateRect?mBound;
privateDrawable?mDrawable;
privateRect?mRect;
privateAnimation?scaleSmallAnimation;
privateAnimation?scaleBigAnimation;
publicFocusRelativeLayout(Context?context)?{
super(context);
init();
}
publicFocusRelativeLayout(Context?context,?AttributeSet?attrs,intdefStyle)?{
super(context,?attrs,?defStyle);
init();
}
publicFocusRelativeLayout(Context?context,?AttributeSet?attrs)?{
super(context,?attrs);
init();
}
protectedvoidinit()?{
setWillNotDraw(false);
mRect?=newRect();
mBound?=newRect();
//獲取焦點(diǎn)后,外側(cè)的陰影圖片
mDrawable?=?getResources().getDrawable(R.drawable.poster_shadow_4);
setChildrenDrawingOrderEnabled(true);
}
@Override
protectedvoidonAttachedToWindow()?{
super.onAttachedToWindow();
}
@Override
publicvoiddraw(Canvas?canvas)?{
super.draw(canvas);
}
@Override
protectedvoidonDraw(Canvas?canvas)?{
if(hasFocus())?{
super.getDrawingRect(mRect);
mBound.set(-5+mRect.left,?-5+mRect.top,5+mRect.right,5+mRect.bottom);
mDrawable.setBounds(mBound);
canvas.save();
mDrawable.draw(canvas);
canvas.restore();
}
super.onDraw(canvas);
}
@Override
protectedvoidonFocusChanged(booleangainFocus,intdirection,?Rect?previouslyFocusedRect)?{
super.onFocusChanged(gainFocus,?direction,?previouslyFocusedRect);
if(gainFocus)?{
bringToFront();
getRootView().requestLayout();
getRootView().invalidate();
zoomOut();
}else{
zoomIn();
}
}
/**
*?縮小動(dòng)畫
*/
privatevoidzoomIn()?{
if(scaleSmallAnimation?==null)?{
scaleSmallAnimation?=?AnimationUtils.loadAnimation(getContext(),?R.anim.anim_scale_small);
}
startAnimation(scaleSmallAnimation);
}
/**
*?放倒動(dòng)畫
*/
privatevoidzoomOut()?{
if(scaleBigAnimation?==null)?{
scaleBigAnimation?=?AnimationUtils.loadAnimation(getContext(),?R.anim.anim_scale_big);
}
startAnimation(scaleBigAnimation);
}
}
(2)定義兩個(gè)放大和縮小的動(dòng)畫文件
放大的動(dòng)畫文件:anim_scale_big.xml
[java]view plaincopy
android:fillAfter="true"
android:fillBefore="false"
android:shareInterpolator="false">
android:duration="500"
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.1"
android:toYScale="1.1"
android:fillAfter="true"/>
縮小的動(dòng)畫文件:anim_scale_small.xml
[java]view plaincopy
android:fillAfter="false"
android:fillBefore="true"
android:shareInterpolator="false">
android:duration="500"
android:fromXScale="1.1"
android:fromYScale="1.1"
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"
android:fillAfter="true"/>
(3)準(zhǔn)備工作就結(jié)束下,下面開始些布局文件恕洲。由于本例子中的圖片布局基本類似塔橡,所以就單獨(dú)給出一個(gè)item文件(例子中使用了圓角圖片梅割,在此不再貼出代碼):
[java]view plaincopy
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/item"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:clickable="true"
android:focusable="true"
android:focusableInTouchMode="true">
android:id="@+id/img"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/mid_bottom"
android:duplicateParentState="true"
android:scaleType="fitXY"
app:roundHeight="@dimen/w_10"
app:roundWidth="@dimen/w_10"/>
android:id="@+id/hover"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@drawable/sl_image_home_navigator"
android:duplicateParentState="true"
android:scaleType="fitXY"
app:roundHeight="@dimen/w_10"
app:roundWidth="@dimen/w_10"/>
(4)引用定義好的子布局:
[java]view plaincopy
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:id="@+id/fragment_two"
android:clipChildren="false"
android:clipToPadding="false">
android:id="@+id/channel_0"
android:layout_width="@dimen/w_320"
android:layout_height="@dimen/h_240"
layout="@layout/home_page_channel_item"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginRight="@dimen/h_15"/>
android:id="@+id/channel_1"
android:layout_width="@dimen/w_320"
android:layout_height="@dimen/h_240"
android:layout_marginTop="@dimen/h_15"
layout="@layout/home_page_channel_item"
android:layout_below="@id/channel_0"
android:layout_marginRight="@dimen/h_15"
android:layout_alignLeft="@id/channel_0"/>
android:id="@+id/channel_2"
android:layout_width="@dimen/w_320"
android:layout_height="@dimen/h_240"
layout="@layout/home_page_channel_item"
android:layout_toRightOf="@id/channel_0"
android:layout_alignTop="@id/channel_0"
android:layout_marginRight="@dimen/h_15"/>
android:id="@+id/channel_3"
android:layout_width="@dimen/w_320"
android:layout_height="@dimen/h_240"
layout="@layout/home_page_channel_item"
android:layout_alignLeft="@id/channel_2"
android:layout_marginTop="@dimen/h_15"
android:layout_marginRight="@dimen/h_15"
android:layout_below="@id/channel_2"/>
android:id="@+id/channel_4"
android:layout_width="@dimen/w_320"
android:layout_height="@dimen/h_240"
layout="@layout/home_page_channel_item"
android:layout_toRightOf="@id/channel_2"
android:layout_alignTop="@id/channel_2"
android:layout_marginRight="@dimen/h_15"/>
android:id="@+id/channel_5"
android:layout_width="@dimen/w_320"
android:layout_height="@dimen/h_240"
layout="@layout/home_page_channel_item"
android:layout_alignLeft="@id/channel_4"
android:layout_marginTop="@dimen/h_15"
android:layout_marginRight="@dimen/h_15"
android:layout_below="@id/channel_4"/>
android:id="@+id/channel_6"
android:layout_width="@dimen/w_320"
android:layout_height="@dimen/h_240"
layout="@layout/home_page_channel_item"
android:layout_toRightOf="@id/channel_4"
android:layout_alignTop="@id/channel_4"
android:layout_marginRight="@dimen/h_15"/>
android:id="@+id/channel_7"
android:layout_width="@dimen/w_320"
android:layout_height="@dimen/h_240"
android:layout_marginTop="@dimen/h_15"
layout="@layout/home_page_channel_item"
android:layout_alignLeft="@id/channel_6"
android:layout_marginRight="@dimen/h_15"
android:layout_below="@id/channel_6"/>
android:id="@+id/channel_8"
android:layout_width="@dimen/w_320"
android:layout_height="@dimen/h_240"
layout="@layout/home_page_channel_item"
android:layout_toRightOf="@id/channel_6"
android:layout_alignTop="@id/channel_6"
android:layout_marginRight="@dimen/h_15"/>
android:id="@+id/channel_9"
android:layout_width="@dimen/w_320"
android:layout_marginTop="@dimen/h_15"
android:layout_height="@dimen/h_240"
layout="@layout/home_page_channel_item"
android:layout_alignLeft="@id/channel_8"
android:layout_marginRight="@dimen/h_15"
android:layout_below="@id/channel_8"/>
最后,在JAVA代碼處理滑動(dòng)到最左側(cè)葛家,最右側(cè)户辞,最下方時(shí)。進(jìn)行模塊切換癞谒,具體代碼如下:
[java]view plaincopy
packagecn.chinaiptv.newaikan.fragment;
importandroid.os.Bundle;
importandroid.support.annotation.Nullable;
importandroid.support.v4.app.Fragment;
importandroid.view.LayoutInflater;
importandroid.view.View;
importandroid.view.ViewGroup;
importandroid.view.ViewTreeObserver;
importandroid.widget.RelativeLayout;
importcn.chinaiptv.newaikan.R;
importcn.chinaiptv.newaikan.view.FocusRelativeLayout;
/**
*?Created?by?ddklsy163com?on?16/12/19.
*/
publicclassFragmentTwoextendsFragmentimplementsViewTreeObserver.OnGlobalFocusChangeListener?{
privateView?view;
privateFocusRelativeLayout?channel_0;
privateFocusRelativeLayout?channel_1;
privateFocusRelativeLayout?channel_2;
privateFocusRelativeLayout?channel_3;
privateFocusRelativeLayout?channel_4;
privateFocusRelativeLayout?channel_5;
privateFocusRelativeLayout?channel_6;
privateFocusRelativeLayout?channel_7;
privateFocusRelativeLayout?channel_8;
privateFocusRelativeLayout?channel_9;
privateRelativeLayout?fragment_two;
@Nullable
@Override
publicView?onCreateView(LayoutInflater?inflater,@NullableViewGroup?container,@NullableBundle?savedInstanceState)?{
if(view?!=null)?{
ViewGroup?parent?=?(ViewGroup)?view.getParent();
if(parent?!=null)?{
parent.removeView(view);
}
returnview;
}
view?=?inflater.inflate(R.layout.fragment_two,null);
initView(view);
fragment_two.getViewTreeObserver().addOnGlobalFocusChangeListener(this);
returnview;
}
privatevoidinitView(View?view)?{
fragment_two?=?(RelativeLayout)?view.findViewById(R.id.fragment_two);
channel_0?=?(FocusRelativeLayout)?view.findViewById(R.id.channel_0);
channel_1?=?(FocusRelativeLayout)?view.findViewById(R.id.channel_1);
channel_2?=?(FocusRelativeLayout)?view.findViewById(R.id.channel_2);
channel_3?=?(FocusRelativeLayout)?view.findViewById(R.id.channel_3);
channel_4?=?(FocusRelativeLayout)?view.findViewById(R.id.channel_4);
channel_5?=?(FocusRelativeLayout)?view.findViewById(R.id.channel_5);
channel_6?=?(FocusRelativeLayout)?view.findViewById(R.id.channel_6);
channel_7?=?(FocusRelativeLayout)?view.findViewById(R.id.channel_7);
channel_8?=?(FocusRelativeLayout)?view.findViewById(R.id.channel_8);
channel_9?=?(FocusRelativeLayout)?view.findViewById(R.id.channel_9);
}
@Override
publicvoidonGlobalFocusChanged(View?oldFocus,?View?newFocus)?{
switch(newFocus.getId())?{
caseR.id.channel_0:
caseR.id.channel_1:
channel_0.setNextFocusLeftId(R.id.tv_one);
channel_1.setNextFocusLeftId(R.id.tv_one);
channel_1.setNextFocusDownId(R.id.tv_two);
caseR.id.channel_8:
caseR.id.channel_9:
channel_8.setNextFocusRightId(R.id.tv_three);
channel_9.setNextFocusRightId(R.id.tv_three);
channel_9.setNextFocusDownId(R.id.tv_two);
break;
caseR.id.channel_2:
caseR.id.channel_3:
caseR.id.channel_4:
caseR.id.channel_5:
caseR.id.channel_6:
caseR.id.channel_7:
channel_3.setNextFocusDownId(R.id.tv_two);
channel_5.setNextFocusDownId(R.id.tv_two);
channel_7.setNextFocusDownId(R.id.tv_two);
break;
}
}
}
到此底燎,就完美實(shí)現(xiàn)了獲取焦點(diǎn)的高亮顯示。