2012-05-30 23 views
9

有沒有辦法在僅接受整數值的首選區段中創建首選項?我可以實現一個EditTextPreference並註冊一個OnPreferenceChangeListener其中我可以拒絕更改,如果用戶輸入一個字符串不是一個數字,但我更喜歡的東西是爲了只持有號碼,並且不允許用戶輸入任何東西,也許只顯示一個撥號盤鍵盤..我沒有這樣的偏好存在,因爲偏好的每個後代被映射到布爾(CheckBoxPreference),一個字符串(* EditTextPreference)或一個字符串數組(MultiSelectListPreference),即沒有偏好映射到整數,但也許有些人可以給我一個提示或至少告訴我是否有比我提出的更好的解決方案ab OVE。灰色提出如何創建只接受整數值的首選項

解決方案:

EditText editText = ((EditTextPreference)  
          findPreference("intent_property")).getEditText(); 
editText.setKeyListener(new NumberKeyListener() { 
    @Override 
    public int getInputType() { 
     // The following shows the standard keyboard but switches to the view 
     // with numbers on available on the top line of chars 
     return InputType.TYPE_CLASS_NUMBER; 
     // Return the following to show a dialpad as the one shown when entering phone 
     // numbers. 
     // return InputType.TYPE_CLASS_PHONE 
    } 

    @Override 
    protected char[] getAcceptedChars() { 
     return new String("1234567890").toCharArray(); 
    } 
}); 

較短的解決方案,即不允許改變鍵盤撥號盤,但需要較少的代碼:

EditText editText = ((EditTextPreference) 
          findPreference("intent_property")).getEditText(); 
editText.setKeyListener(new DigitsKeyListener()); 

我不喜歡這個解決方案只是一件事:用戶可以輸入0000,並將其接受並保存在共享首選項(這是一個字符串)爲「0000」..這需要你實現OnSharedPreferenceChangeListener來攔截對共享首選項的更改並刪除此首選項中的前導零或直接在此首選項上實現更改偵聽器,並返回false以拒絕具有尾隨零的數字(告訴我是否存在針對最後一個問題的更好解決方案不涉及實施您自己的偏好)。這將是美的,如果我們可以修改NEWVALUEOnPreferenceChangeListener ..

+0

你怎麼樣採取['的的EditTextPreference'源(http://grepcode.com/file/repository.grepcode.com/java/ext/com.google。 android/android/4.0.4_r1.2/android/preference/EditTextPreference.java#EditTextPreference)作爲起點,並將所有與字符串相關的方法替換爲基於int的對應方法?對我來說似乎很簡單。此外,從那時起,您可以直接訪問「EditText」對象,您可以根據自己的喜好設置任意數字輸入類型。 –

+0

@MH如果我以編程方式管理首選項,似乎很簡單,但如果我創建* EditTextIntegerPreference *,例如,我不能在傳遞給* PreferenceFragment *的XML文件中使用它,或者有辦法註冊一個新的XML標籤映射到我的新對象? –

+1

您可以像使用自定義視圖一樣使用xml文件中的自定義首選項。只需提供完全合格的課程名稱;例如'com.costanzi.gianni.example.ExamplePreference'。有關示例,請參閱[此API演示](http://developer.android.com/resources/samples/ApiDemos/res/xml/advanced_preferences.html)。 –

回答

6

在閱讀提出的解決方案之後,我仍然認爲自定義首選項是最佳選擇。我確實以粗體文字閱讀了你的評論,但是設置一個基本的EditTextIntegerPreference實際上是非常簡單的,它將解決用戶輸入例如「0000」時存在的問題。

只是說明了面前:因爲你通常希望能夠使用偏好幾個地方在你的應用程序,就我而言,一個EditTextIntegerPreference的正確實施將其存儲針對Integer值。這樣你就可以在任何地方檢索int值,而不需要先解析或轉換它。

但是,爲了保持這個答案的重點和緊湊,我實際上會展示一個常規EditTextPreference的擴展,這意味着在引擎蓋下,該值仍然會以字符串形式存儲。如果你真的熱衷於讓「正確」的實施工作,我不介意後來寫。儘管如此,你可能會首先想自己破解它。 :)

public class EditTextIntegerPreference extends EditTextPreference { 

    private Integer mInteger; 

    public EditTextIntegerPreference(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     getEditText().setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED); 
    } 

    public EditTextIntegerPreference(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     getEditText().setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED); 
    } 

    public EditTextIntegerPreference(Context context) { 
     super(context); 
     getEditText().setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED); 
    } 

    @Override public void setText(String text) { 
     final boolean wasBlocking = shouldDisableDependents(); 
     mInteger = parseInteger(text); 
     persistString(mInteger != null ? mInteger.toString() : null); 
     final boolean isBlocking = shouldDisableDependents(); 
     if (isBlocking != wasBlocking) notifyDependencyChange(isBlocking); 
    } 

    @Override public String getText() { 
     return mInteger != null ? mInteger.toString() : null; 
    } 

    private static Integer parseInteger(String text) { 
     try { return Integer.parseInt(text); } 
     catch (NumberFormatException e) { return null; } 
    }  
} 

之所以這樣,解決了「0000」的問題,就是我們只是鑄造用戶輸入的值,以int類型之前,我們保存它,然後重新插入到在檢索的字符串。這意味着任何前導零(當然除了'0')都會自動消失。

的「數字」輸入型將限制用戶僅輸入輸入數字,所以parseInteger(...)方法主要存在於理智的原因,雖然會趕上NumberFormatException如果你試圖輸入一個空或null字符串。再次,你可以使這個更漂亮,我現在還沒有做。

+0

很多很多很多非常感謝你爲我花費的時間,你的例子很清楚..我發現很奇怪他們沒有提供這樣的偏好的屬性,以便說「它只能接受數字在這種情況下,它必須保存到一個Integer/Float「上,但是實現像你這樣的解決方案並不是太沉重..另一種可能的解決方案是監聽屬性更改,以及何時該屬性更改,獲取字符串值並在整數(刪除前導零),因爲我確信它只包含數字。 –

+0

@Gianni Costanzi:關於你提到的另一種可能的解決方案:這是毫無疑問的,儘管擁有一個專用的首選類的好處是邏輯很好地自包含並從其他非相關代碼中抽象出來。儘管如此,所有的工作都是一樣的,所以你可以做到。 :) –

+0

你是完全正確的,恕我直言,你的解決方案是更好的,因爲獨立..謝謝 –

1

我猜ü可以調用getEditText()得到的EditText OBJ,然後調用setKeyListener用NumberKeyListener。

+0

我會盡快嘗試,謝謝你的建議! –

+0

我試過你告訴我的,它完美地工作,看看我添加了這段代碼的主要帖子。再次,非常感謝! –

+0

如果您對上面編寫的代碼有進一步的建議,歡迎您! –

29

有一個更簡單的方法來做到這一點。只需在XML中的EditTextPreference中設置爲android:numeric =「integer」(您可以將其設置爲整數,帶符號或十進制)。 Eclipse(或者你正在使用的任何工具)不會告訴你這是一個可能的屬性,而只是寫在你的EditTextPreference中並清理你的項目。你會看到它不會給你任何錯誤。 :)

+0

這是正確的答案 – Basic

1

你應該使用PreferenceActivity,它基本上用來顯示偏好,如xm​​l文件。在此活動中,您可以使用複選框,編輯文本並將值保存到首選項。

+0

你可以提供一個OP的例子代碼片段? – GHC

0

當您嘗試parseInt()數字後發生異常時,您也可以重新打開對話框。 下面是一個示例代碼:

public class MyEditTextPreference extends EditTextPreference { 

     private EditText _editText; 

     public MyEditTextPreference(Context context, AttributeSet attrs) { 
      super(context, attrs); 
      _editText = getEditText(); 
     } 

     @Override 
     public void onDismiss(DialogInterface dialog) { 

      super.onDismiss(dialog); 

      try { 
       Integer.parseInt(_editText.getText().toString()); 
      } catch (NumberFormatException e) { 

       ((Dialog) dialog).show(); 
      } 
     } 
    }