最近無心間看到了涉及到跑馬燈效果的代碼,因而在網上查閱了不少資料,在這裏對本身看的一些文章進行一下總結,順便加上本身的一些體會。html
讓咱們一步步逐漸向下。android
首先咱們要實現走馬燈這樣一個效果,一般來講都是在TextView這個控件中來實現的,並且其中的文字必定是單行顯示,若是多行顯示,那走馬燈效果api
也就失去了存在的意義。另外,在EditText中使用走馬燈沒有必要,也不合理,實際上對於EditText來講android:ellipsize這個屬性只有對於設置在android:hint中的文字測試
的時候是有用的,並且android:ellipsize="marquee"這個用法不能用在EditText控件上。對於在EditText用戶輸入的文字,android:ellipsize這個屬性沒有用處。關於EditTextspa
設置android:ellipsize的相關用法之後再講,在這裏也算留個標記,以防本身忘了。xml
在TextView中實現咱們的走馬燈效果,須要兩個屬性android:singleLine="true",以及android:ellipsize="marquee",咱們來看下面的代碼:htm
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical" >
-
- <TextView
- android:layout_width="100dip"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:text="走馬燈效果的演示"
- android:singleLine="true"
- android:ellipsize="marquee"/>
-
- </LinearLayout>
運行這段代碼以後,咱們會發現走馬燈效果並無顯示出來,顯示出的文字是不動的,實際效果以下:ip
這其中的緣由在於跑馬燈效果須要TextVIew得到當前的焦點(focus)。然而對於TextView這個控件來講,他的默認的Clickable,LongClickable,Focusable,utf-8
FocusableInTouchMode這四個屬性的值都是false,因此跑馬燈效果也就不會出來了,即便你用手觸摸TextView或者按下手機上的導航按鍵(如今的手機沒這get
個東東了都。。。)也是沒法顯示跑馬燈的效果的。
解決這個問題咱們就須要讓咱們的TextView獲得焦點,這裏主要涉及android:focusable和android:focusableInTouchMode這兩個屬性,簡單來講把這兩個屬性都設置成
true,那麼在運行程序之後跑馬燈效果就顯示出來了,這裏就再也不貼這兩行代碼了。
可是細細品味這兩個屬性以後發現其中其實仍是有一些玄機的:
1.。若是這兩個屬性設置成android:focusable="true"以及android:focusableInTouchMode="false",那麼會發現程序運行以後,走馬燈效果沒有出現,
這個時候須要用戶按下手機或者模擬器上的上下導航鍵,才能讓走馬燈的效果出現,這說明android:focusable是針對於手機按鍵有效的,然而根據api的解釋,
android:focusableInTouchMode是根據屏幕觸摸決定的。
2。若是這兩個屬性設置成android:focusable="false"與android:focusableInTouchMode="true",那麼不管如何走馬燈都出現不了了,就算加上android:clickable="true"
也不行,這說明 android:focusable="true"是android:focusableInTouchMode="true"能有效的先決條件,我推測多是在源碼實現中,android:focusableInTouchMode
的邏輯是嵌套在android:focusable中的,這個有待於之後進一步的研究,路漫漫其修遠兮。。。
3。在把這兩個屬性都設置成true之後,會發現程序運行以後,走馬燈效果自動就顯現了出來,這說明應用在運行後,會自動地按照某種順序(在這裏應該是自上而下),
尋找第一個android:focusableInTouchMode="true"這個屬性有效的第一個控件,固然要使這個屬性有效按照前面的討論android:focusable="true"也必須具有。根據測試,
LinearLayout的Clickable,LongClickable,Focusable,FocusableInTouchMode這四個屬性默認也都是false,所以,在上面的例子中TextView就率先得到了焦點,
走馬燈也就走了起來了。
這裏咱們作一下驗證,首先將代碼修改成:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
- android:focusable="true">
-
- <TextView
- android:layout_width="100dip"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:text="走馬燈效果的演示"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:focusable="true"
- android:focusableInTouchMode="true"
- ></TextView>
-
- </LinearLayout>
也就是爲LinearLayout加上了android:focusable="true"而後運行應用,會發現TextView的走馬燈照走不誤:
而後咱們爲LinearLayout加上android:focusableInTouchMode="true"而後再運行,會發現走馬燈失效了。
這裏也就驗證了咱們總結的第三條結論。
可是稍等,咱們在這裏又發現問題了!如今不管咱們怎麼點擊導航按鈕,又或是點擊屏幕上的TextView走馬燈死活都走不出來了。這是怎麼回事呢?
讓咱們理順一下思路,按照咱們前面的總結,走馬燈要想有效,TextView必需要獲得焦點,如今走馬燈出不來,說明TextView沒有獲得焦點。
這裏有兩個狀況,一是導航按鈕沒法讓TextView或得焦點,二是屏幕點擊沒法讓TextView得到焦點。
先看第一種狀況,第一種狀況的緣由在於使用導航按鈕切換焦點默認的的方式會跳過內部控件,說白了,上面例子裏面的TextView在LinearLayout裏面,如今
LinearLayout有焦點,若是你按導航按鈕上下按鍵,焦點只會在LinearLayout同層次的控件之間切換,不會進入到Linearlayout內部,爲了驗證這個結論,咱們使用
下面的代碼:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
- >
- <LinearLayout android:layout_width="fill_parent"
- android:layout_height="100dip"
- android:focusable="true"
- android:focusableInTouchMode="true"/>
- <TextView
- android:layout_width="100dip"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:text="走馬燈效果的演示"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:focusable="true"
- android:focusableInTouchMode="true"
- ></TextView>
-
- </LinearLayout>
而後咱們運行程序,會發現開始的時候走馬燈沒有自動運行,由於這時候焦點在代碼裏面的第二個LinearLayout那裏,而後咱們按下導航下按鍵,會發現走馬燈效果出來了,
這裏我就不貼圖了。
可是稍等,再從新運行應用,不要按導航按鍵,而後咱們這個時候用手指或者說模擬器裏的鼠標繼續點擊TextView,會發現走馬燈仍是沒有出現。
這個時候咱們來到了第二種狀況了。
這裏的問題能夠總結爲,除了應用第一次開啓的時候,應用自動尋找到android:focusableInTouchMode="true"屬性有效的控件冰賦予焦點,咱們要如何
自行經過點擊屏幕的方式使一個控件得到焦點,在這種狀況之下控件想要得到焦點的流程是什麼。
這方面的資料我沒有查到,因此只能本身作一些試驗,而後總結。有盲人摸象的嫌疑,可是我認爲在某種程度上是管用的,繼續。
首先咱們將代碼修改成以下所示:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
- >
- <LinearLayout android:layout_width="fill_parent"
- android:layout_height="100dip"
- android:focusable="true"
- android:focusableInTouchMode="true"
- />
- <TextView
- android:layout_width="100dip"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:text="走馬燈效果的演示"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:clickable="true"
- android:focusable="true"
- android:focusableInTouchMode="true"
- ></TextView>
-
- </LinearLayout>
也就是給TextView加上了一個android:clickable="true"屬性,而後運行以後發現,如今經過觸摸的方式點擊TextView可讓走馬燈初顯也就是可讓
TextView得到焦點了。
看起來問題解決了,可是仔細想一想其中仍是有一些值得思考的地方:
android:clickable與android:focusableInTouchMode之間是一種什麼關係?是說一個空間若是要想能得到焦點就必須可點擊嗎?又或者說一個空間只要能夠點擊
就必定能夠得到焦點?這兩者之間是充要條件仍是充分條件仍是必要條件?
咱們來作一下驗證:
首先運行以下代碼:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
- >
- <LinearLayout android:layout_width="fill_parent"
- android:layout_height="100dip"
- android:clickable="true"
- />
- <TextView
- android:layout_width="100dip"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:text="走馬燈效果的演示"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:clickable="true"
- android:focusable="true"
- android:focusableInTouchMode="true"
- ></TextView>
-
- </LinearLayout>
運行後會發現,應用開始之後跑馬燈立刻出現,鼠標點擊TextView上方的位置也就是第二個LinearLayout的區域,跑馬燈不中止,這說明:
android:clickable="true"不必定就能得到焦點,也就是一個空間能點擊不必定就能得到焦點。
咱們來看下一段代碼:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
- >
- <LinearLayout android:layout_width="fill_parent"
- android:layout_height="100dip"
- android:clickable="false"
- android:focusable="true"
- android:focusableInTouchMode="true"
- />
- <TextView
- android:layout_width="100dip"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:text="走馬燈效果的演示"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:clickable="true"
- android:focusable="true"
- android:focusableInTouchMode="true"
- ></TextView>
-
- </LinearLayout>
這段代碼運行以後,首先代碼中的第二個LinearLayout自動得到焦點,而後咱們點擊TextView。跑馬燈出現,TextView得到焦點,而後咱們點擊TextView上方區域,
跑馬燈不中止。這說明若是一個空間能得到觸摸模式焦點但卻不能點擊,那麼在觸摸模式下不管怎麼觸摸也仍是不能得到焦點的。
好的咱們來看最後一段代碼:
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical"
- >
- <LinearLayout android:layout_width="fill_parent"
- android:layout_height="100dip"
- android:clickable="true"
- android:focusable="true"
- android:focusableInTouchMode="true"
- />
- <TextView
- android:layout_width="100dip"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:text="走馬燈效果的演示"
- android:singleLine="true"
- android:ellipsize="marquee"
- android:clickable="true"
- android:focusable="true"
- android:focusableInTouchMode="true"
- ></TextView>
-
- </LinearLayout>
這段代碼運行以後,首先走馬燈不出現,代碼中的第二個LinearLayout得到焦點,而後咱們點擊第二個TextView,走馬燈出現,而後咱們點擊TextView上方的區域,
走馬燈效果消失,說明焦點轉移到代碼中的第二個LinearLayout。
好的,總結一下也就是說,在觸摸模式下android:clickable="true"是(android:focusable="true",android:focusableInTouchMode="true")能得到焦點的必要條件,
就是說一個控件想要在觸摸模式下得到焦點就必定要可點擊,上面三個屬性都要有。