2013-12-16 24 views
1

我在ViewPager內有FragmentEditText .setError()不適用重新創建我的自定義錯誤圖標

在該片段,我有幾個EditText其OnTextChanged聽衆(在onViewCreated方法加入)做一些驗證工作,並調用一個函數來設置/刪除錯誤,例如:

// Sets or removes an error message in the nameField EditText 
public void validateUsername(String message) 
{ 
    if(message == null) 
    { 
     nameField.setError(null); 
    } 
    else 
    { 
     nameField.setError(message,errorIcon); 
    } 
} 

的errorIcon是Drawable實例化onCreate這樣的:

errorIcon = getResources().getDrawable(R.drawable.ic_wrong_input); 
errorIcon.setBounds(new Rect(0, 0, errorIcon.getIntrinsicWidth(), errorIcon.getIntrinsicHeight())); 

當我鍵入的EditText的東西,確認工作正常:顯示我的錯誤信息,用我的自定義圖標。

但是,當我旋轉裝置,該validateUsername()函數被調用(預期的行爲),在else分支nameField.setError(message,errorIcon)得到執行,但EditText得到Android的默認錯誤圖標,而不是我的(是的,在調試時,我可以看到,我的errorIcon Drawable是instanciated)。之後,如果我在EditText中輸入了無效的內容,則再次調用驗證方法,這次我再次獲得自定義錯誤圖標。如果我再次旋轉設備,同樣的事情:重新創建默認圖標,我輸入的東西無效後的自定義圖標...

任何人都可以解釋這種行爲?爲什麼我會在設備旋轉造成重新創建後獲取Android的默認錯誤圖標,即使我明確設置了自定義錯誤圖標?

編輯:

我試着在我validateUsername()方法instanciating的繪製對象,但沒有奏效。

編輯2:

我想,這樣它融合了我的用戶界面也更好地使用自定義錯誤圖標是因爲我使用的是另一個自定義圖標(綠色的),顯示了作爲EditText s'的右邊Drawable當他們的輸入是有效的,我希望他們是一致彼此。

現在我已經辭職了,我讓Android使用默認錯誤圖標(即,我沒有在setError()方法中指定任何Drawable)。當輸入有效時,我將EditText的右邊的Drawable設置爲我自定義的「input is valid」圖標,爲了一致性,我修改了它的大小與Android的indicator_input_error.png相同。

但是,我不喜歡這種方法(例如在將來的版本中,indicator_input_error.png圖標可能會不同),我無法理解爲什麼當Fragment被重新創建時我仍然得到默認圖標。奇怪的是,第一次Fragment被重新創建,如果EditText驗證失敗,並且validateUsername()被非空消息調用,我得到我的自定義圖標。第二次(等等)Fragment被重新創建,我得到了Android的默認圖標。如果我輸入了一些無效的文本,我再次得到我的自定義圖標,這非常奇怪。

+0

你可以嘗試的另一件事是調用nameField – Lovis

+0

上的'requestFocus'不行,那也行不通。 – user1987392

回答

4

真是麻煩!我遇到了同樣的問題。除了內置的錯誤圖標之外,我還有一個自定義圖標來表示警告,並根據情況顯示相應的圖標。

當你運行到,當onSave/onRestoreInstanceState()在你的活動中被調用時(即:當屏幕旋轉時),setError()會運行amok。事實證明,大多數(所有?)股票Android小部件都創建了自己的可分派狀態,以在輪換期間保留其彈子。這意味着許多簡單的佈局不需要實現自己的可分段/可序列化對象,就像您最有可能遇到的那樣。

如果你深入到TextView的類,你會在其onRestoreInstanceState結束()執行看到以下內容:

 if (ss.error != null) { 
     final CharSequence error = ss.error; 
     // Display the error later, after the first layout pass 
     post(new Runnable() { 
      public void run() { 
       setError(error); 
      } 
     }); 

正如你所看到的,ss.error(這是在TextView中的保存onSaveInstanceState())只檢查它是否不爲空。如果是這樣,它會通過調用setError(錯誤)來恢復。簡而言之,您的自定義圖標在保存期間不會被放置,因此它不會被Widget恢復 - 導致顯示標準的紅色錯誤圖標。鑑於TextView代碼的年齡,我懷疑這是Google的疏忽。

可以嘗試重置錯誤文本和圖標在自己的覆蓋onRestoreInstanceState(),但由於小部件排隊其SETERROR()調用(通過調用的方式張貼()),您的直接通話將超出它,導致您的圖標顯示一秒鐘,只有在隊列處理髮生時才被覆蓋。

我解決了這個問題,通過將我自己的調用setError()放入我的視圖的隊列中(也使用post())。這可能不是學術上的正確和吱吱聲乾淨的同步(因爲我依賴消息隊列處理順序),但它解決了這個問題。

總之,做這樣的事情在你的onRestoreInstanceState():

protected void onRestoreInstanceState(Bundle savedInstanceState) 
{ 
    // Call super first, to ensure that all the widget updates get in the queue first... 
    super.onRestoreInstanceState(savedInstanceState); 

    View view = getWindow().getDecorView().getRootView(); 

    view.post(new Runnable() 
    { 
     public void run() 
     { 
      myEditText.setError(...); 
      . 
      . 
      . 
     } 
    }); 
} 

這是很多消化。希望這可以幫助!

+0

良好的研究和良好的答案。我還沒有測試過,但它非常有意義。謝謝! – user1987392