android tv焦點特效實現淺析,androidtv焦點淺析
Android TV上的焦點凸顯特效相信大家都看到過,那麼我們就來實現它吧,首先上張。
先說一下實現原理,主要通過重寫RelativeLayout實現item,之後在其中加入scalanimation動畫效果。剛開始處理時,還是發現了一些問題,比如item放大後會被其他item遮擋,如何添加選中邊框等等,以及動畫的實現等等。下面放上實現細節。
首先是item的代碼:
<view xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/item" android:layout_width="@dimen/home_channel_item_width" android:layout_height="@dimen/home_channel_item_height" class="com.eastelsoft.tv.widget.home.HomeItemContainer" android:clickable="true" android:focusable="true" android:focusableInTouchMode="true" android:clipChildren="false" android:clipToPadding="false" > <com.eastelsoft.tv.widget.ESImageView android:id="@+id/img" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/holder_nor" android:duplicateParentState="true" android:scaleType="fitXY" /> <!-- --> <com.eastelsoft.tv.widget.ESImageView android:id="@+id/hover" android:layout_width="fill_parent" android:layout_height="fill_parent" android:contentDescription="@string/desc" android:duplicateParentState="true" android:scaleType="fitXY" android:src="@drawable/sl_image_home_navigator" /> <TextView android:id="@+id/text" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_marginBottom="@dimen/home_item_text_margin" android:layout_marginLeft="@dimen/home_item_text_margin" android:layout_marginRight="@dimen/home_item_text_margin" android:ellipsize="marquee" android:gravity="bottom|right|center" android:includeFontPadding="false" android:marqueeRepeatLimit="5" android:maxWidth="@dimen/px310" android:shadowColor="#88333333" android:shadowDx="2.0" android:shadowDy="2.0" android:shadowRadius="2.0" android:singleLine="true" android:textColor="#ffffffff" /></view>
這裡定義了一個自訂view,代碼在後面放上,每個item裡添加了一個img,用於放置內容圖片,一個hover,用於顯示選中的邊框,以及一個text,顯示一些文字說明。
hover的src是一個selector drawable,當未focus時,它的背景是tansparent,當focus,放入外框圖片。
自訂的HomeItemContainer 代碼:
public class HomeItemContainer extends RelativeLayout {private Animation scaleSmallAnimation;private Animation scaleBigAnimation;public HomeItemContainer(Context context) {super(context);}public HomeItemContainer(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}public HomeItemContainer(Context context, AttributeSet attrs) {super(context, attrs);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);}@Overrideprotected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {super.onFocusChanged(gainFocus, direction, previouslyFocusedRect);if (gainFocus) {this.bringToFront();getRootView().requestLayout();getRootView().invalidate();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);}}
注意onFocusChanged方法,為防止item被其他item遮擋,先調用bringToFront方法,使此item處於最上層,之後調用父view的方法進行重新繪製,其實注意一點,item必須處於同一父view中,否則requestLayout和invalidate可能會不起作用。
順便放上一個scaleanimation縮小的效果代碼:
<?xml version="1.0" encoding="utf-8"?><set xmlns:android="http://schemas.android.com/apk/res/android" android:fillAfter="false" android:fillBefore="true" android:shareInterpolator="false" > <scale android:duration="200" 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" /></set>
裡面的屬性就不詳細介紹了,有興趣的可以自己Google。
最後放上item的父view:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" android:padding="10dp" android:clipChildren="false" android:clipToPadding="false" > <include android:id="@+id/channel_0" android:layout_width="@dimen/home_channel_item_width" android:layout_height="@dimen/home_channel_item_height" layout="@layout/home_page_channel_item" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_margin="3dp" /> <include android:id="@+id/channel_1" android:layout_width="@dimen/home_channel_item_width" android:layout_height="@dimen/home_channel_item_height" layout="@layout/home_page_channel_item" android:layout_below="@id/channel_0" android:layout_alignLeft="@id/channel_0" /> <include android:id="@+id/channel_2" android:layout_width="@dimen/home_channel_item_width" android:layout_height="@dimen/home_channel_item_height" layout="@layout/home_page_channel_item" android:layout_toRightOf="@id/channel_0" android:layout_alignTop="@id/channel_0" android:layout_marginRight="3dp" android:layout_marginBottom="3dp"/> <include android:id="@+id/channel_3" android:layout_width="@dimen/home_channel_item_width" android:layout_height="@dimen/home_channel_item_height" layout="@layout/home_page_channel_item" android:layout_alignLeft="@id/channel_2" android:layout_below="@id/channel_2"/> <include android:id="@+id/channel_4" android:layout_width="@dimen/home_channel_item_width" android:layout_height="@dimen/home_channel_item_height" layout="@layout/home_page_channel_item" android:layout_toRightOf="@id/channel_2" android:layout_alignTop="@id/channel_2" android:layout_marginRight="3dp" android:layout_marginBottom="3dp"/> <include android:id="@+id/channel_5" android:layout_width="@dimen/home_channel_item_width" android:layout_height="@dimen/home_channel_item_height" layout="@layout/home_page_channel_item" android:layout_alignLeft="@id/channel_4" android:layout_below="@id/channel_4"/> <include android:id="@+id/channel_6" android:layout_width="@dimen/home_channel_item_width" android:layout_height="@dimen/home_channel_item_height" layout="@layout/home_page_channel_item" android:layout_toRightOf="@id/channel_4" android:layout_alignTop="@id/channel_4" android:layout_marginRight="3dp" android:layout_marginBottom="3dp"/> <include android:id="@+id/channel_7" android:layout_width="@dimen/home_channel_item_width" android:layout_height="@dimen/home_channel_item_height" layout="@layout/home_page_channel_item" android:layout_alignLeft="@id/channel_6" android:layout_below="@id/channel_6"/> <include android:id="@+id/channel_8" android:layout_width="@dimen/home_channel_item_width" android:layout_height="@dimen/home_channel_item_height" layout="@layout/home_page_channel_item" android:layout_toRightOf="@id/channel_6" android:layout_alignTop="@id/channel_6" android:layout_marginRight="3dp" android:layout_marginBottom="3dp"/> <include android:id="@+id/channel_9" android:layout_width="@dimen/home_channel_item_width" android:layout_height="@dimen/home_channel_item_height" layout="@layout/home_page_channel_item" android:layout_alignLeft="@id/channel_8" android:layout_below="@id/channel_8"/></RelativeLayout>
這裡我定義了10個item,注意RelativeLayout的兩個屬性,clipChildren設定false,讓children view可以超出自身所設定的大小,clipToPadding設定為false,讓children view可以使用padding 的位置進行繪製,有了這2個屬性,item就可以實現放大而不被遮擋了。
好了,焦點特效的教程就說到這裡了,有問題可以在評論中反饋。
[Android 介面開發] ui中焦點平滑移動動畫,歡迎大家熱烈討論一下
樓主,你提的這個問題,幾乎是個很難解決的問題啊。很多人怕拉低了被採納率而不敢回答,我就豁出去了,反正我的被採納率也不高。
樓主應該是個技術控,呵呵。
ListView和GridView焦點移動確實不平滑,樓主想做平滑,或者想做體驗更好的特效吧?就只能自己去重寫onDraw函數了。這樣還是不好解決,就算繼承了ListView和GridView都不好搞。最好的辦法是:自己去繼承View,然後實現ListView或GridView的功能外,再另外實現焦點移動效果。
就像前段時間,我用到了一個向右滑動的SlidingDrawer,事實上,android系統裡是沒有向右滑動的SlidingDrawer的,它只能上滑和左滑。我在網上下載了一段代碼,是一個外國哥們自己實現的,他寫了個類繼承了LinearLayout,實現了SlidingDrawer所有功能,並且向右滑動。我拿來修改了一下,發現確實很好用。我們也可以仿照實現啊,自己實現一個ListView或GridView。目前上班項目緊,等哪天稍微閑點了,我會研究一下吧。
得趕緊敲代碼了,被技術經理逮到上網閑逛不好。
good day, buddy.
問一下android設定焦點效果的問題
這些應該是很基本問題,到網上找答案 還不如翻書來的快