Android TV 控件獲取焦點(diǎn)特效

最近開始接觸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)的高亮顯示。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末弹砚,一起剝皮案震驚了整個(gè)濱河市双仍,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌桌吃,老刑警劉巖朱沃,帶你破解...
    沈念sama閱讀 216,544評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異茅诱,居然都是意外死亡逗物,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門瑟俭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來敬察,“玉大人,你說我怎么就攤上這事尔当×觯” “怎么了?”我有些...
    開封第一講書人閱讀 162,764評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵椭迎,是天一觀的道長锐帜。 經(jīng)常有香客問我,道長畜号,這世上最難降的妖魔是什么缴阎? 我笑而不...
    開封第一講書人閱讀 58,193評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮简软,結(jié)果婚禮上蛮拔,老公的妹妹穿的比我還像新娘。我一直安慰自己痹升,他們只是感情好建炫,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著疼蛾,像睡著了一般肛跌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,182評(píng)論 1 299
  • 那天衍慎,我揣著相機(jī)與錄音转唉,去河邊找鬼。 笑死稳捆,一個(gè)胖子當(dāng)著我的面吹牛赠法,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播乔夯,決...
    沈念sama閱讀 40,063評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼期虾,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了驯嘱?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,917評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤喳坠,失蹤者是張志新(化名)和其女友劉穎鞠评,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體壕鹉,經(jīng)...
    沈念sama閱讀 45,329評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡剃幌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了晾浴。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片负乡。...
    茶點(diǎn)故事閱讀 39,722評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖脊凰,靈堂內(nèi)的尸體忽然破棺而出抖棘,到底是詐尸還是另有隱情,我是刑警寧澤狸涌,帶...
    沈念sama閱讀 35,425評(píng)論 5 343
  • 正文 年R本政府宣布切省,位于F島的核電站,受9級(jí)特大地震影響帕胆,放射性物質(zhì)發(fā)生泄漏朝捆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評(píng)論 3 326
  • 文/蒙蒙 一懒豹、第九天 我趴在偏房一處隱蔽的房頂上張望芙盘。 院中可真熱鬧,春花似錦脸秽、人聲如沸儒老。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽贷盲。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間巩剖,已是汗流浹背铝穷。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留佳魔,地道東北人曙聂。 一個(gè)月前我還...
    沈念sama閱讀 47,729評(píng)論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像鞠鲜,于是被迫代替她去往敵國和親宁脊。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容