PersistInt slowing down button response in custom preference - android

I've created a custom preference that embeds two buttons (here I have subclassed Button as FastButton). The problem is executing the persistInt to store the preference drastically slows down the response of the button.
I had the notion of only executing the persistInt when the preference's lifecycle is ended, but could not find an appropriate method to override (i.e. there is nothing like onPause() for the Preference class).
I was also unsuccessful at trying to use AsyncTask to move the persistInt off of the UI thread.
Any suggestions about how I should go about mitigating the effect of persistInt on my UI response?
public final class StepperPreference extends Preference {
public int mCurrentValue = 1;
public int maxValue = Integer.MAX_VALUE;
public int minValue = Integer.MIN_VALUE;
private TextView mText;
private FastButton plusButton;
private FastButton minusButton;
public StepperPreference(Context context) {
super(context);
}
public StepperPreference(Context context, AttributeSet attrs) {
super(context, attrs);
parseCustomAttributes(attrs);
}
public StepperPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
parseCustomAttributes(attrs);
}
public void setmCurrentValue(int value) {
if (mCurrentValue != value) {
mCurrentValue = value;
persistInt(mCurrentValue);
}
}
private void parseCustomAttributes(AttributeSet attrs) {
int maxValueAttrInt=Integer.MAX_VALUE;
int minValueAttrInt=Integer.MIN_VALUE;
if (attrs!=null) {
TypedArray a=getContext()
.obtainStyledAttributes(attrs,
R.styleable.StepperPreference,
0, 0);
maxValueAttrInt = a.getInt(R.styleable.StepperPreference_maxValue, Integer.MAX_VALUE);
minValueAttrInt = a.getInt(R.styleable.StepperPreference_minValue, Integer.MIN_VALUE);
a.recycle();
}
if (maxValueAttrInt > minValueAttrInt) {
maxValue = maxValueAttrInt;
minValue = minValueAttrInt;
}
}
#Override
protected View onCreateView(ViewGroup parent) {
LayoutInflater li = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = (View) li.inflate(R.layout.stepper_preference, parent, false);
mText = (TextView) view.findViewById(R.id.text_view);
Context context = getContext();
int localDefaultValue = 0;
mCurrentValue = getPersistedInt(localDefaultValue);
mText.setText(Integer.toString(mCurrentValue));
plusButton = (FastButton) view.findViewById(R.id.plus_button);
plusButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (mCurrentValue < maxValue) {
mCurrentValue++;
mText.setText(Integer.toString(mCurrentValue));
persistInt(mCurrentValue);
}
}
});
minusButton = (FastButton) view.findViewById(R.id.minus_button);
minusButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if (mCurrentValue > minValue) {
mCurrentValue--;
mText.setText(Integer.toString(mCurrentValue));
persistInt(mCurrentValue);
}
}
});
return view;
}
#Override
protected Object onGetDefaultValue(TypedArray a, int index) {
int localDefaultValue = 0;
Object result = a.getInt(index, localDefaultValue);
return result;
}
#Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
int localDefaultValue = 0;
setmCurrentValue(restoreValue ? this.getPersistedInt(localDefaultValue) : (int) defaultValue);
}
}

CheckBoxPreference, via its TwoStatePreference superclass, uses persistBoolean() for saving the preference value, much as you are using persistInt(). I do not perceive significant latency in the processing of the CheckBox. This means one of two things:
I'm a troglodyte and am incapable of seeing obvious delays in animations and such
CheckBoxPreference does not exhibit the problems that you are seeing in your StepperPreference
note: these two possibilities are not mutually exclusive
If we assume #2 to be correct, then there's something else afoot. Method tracing, to see where you are spending time "downstream" from persistInt(), may prove useful for determining what is different about StepperPreference.
From your comment, you had a listener responding to preference changes, and that was what was causing the sluggish response. "Inline" preferences, like CheckBoxPreference and StepperPreference, will be somewhat more "twitchy" than DialogPreference subclasses like ListPreference, simply because it takes less work to change the preference state (e.g., one screen tap versus 2+). As a result, listeners need to be cheaper. For example, you might hold off on doing significant work until the user has left the PreferenceFragment and so you know that the preference values are likely to be stable for at least a second or so.

Related

SwitchButton (in custom view) value is not checked after rotation

I need to create custom view - TextView and Switch button.
I have custom view:
public class CustomTextWithSwitch extends LinearLayout implements View.OnClickListener {
private CustomTextWithSwitchBinding binding;
private boolean defaultValue;
public CustomTextWithSwitch(Context context) {
this(context, null);
}
public CustomTextWithSwitch(Context context, #Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomTextWithSwitch(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
binding = CustomTextWithSwitchBinding.inflate(LayoutInflater.from(getContext()), this);
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CustomTextWithSwitch);
defaultValue = a.getBoolean(R.styleable.CustomTextWithSwitch_defaultValue, false);
a.recycle();
}
#Override
protected void onFinishInflate() {
...
binding.sToggle.setChecked(defaultValue);
super.setOnClickListener(this);
super.onFinishInflate();
}
public void toggle() {
binding.sToggle.toggle();
defaultValue = binding.sToggle.isChecked();
}
#Override
public void onClick(View view) {
toggle();
}
public void setDefaultValue(boolean defaultValue) {
this.defaultValue = defaultValue;
binding.sToggle.setChecked(defaultValue);
}
}
I use that in the activity:
public class MyActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
...
myCustomView.setDefaultValue(true);
}
}
When I open this activity, everything works as expected - switch button is checked. However, when I rotate the screen, it is checked to false. Can somebody advise what am I doing incorrectly? Note: I use ViewModel and the value is restored correctly. However, the Switch button in this custom view is not toggled.
UPDATE: This issue happens only when I have another CustomTextWithSwich in my activity, so it means they have effect on each other(it seems that default value is set according to second View). Is it possible to separate them, so they are standalone?
I suggest you to use a ViewModdel. During rotation it is normal that you will lost the states. ViewModel will not be destroyed during app rotation so the last state of CustomTextWithSwich will be not lost.
On the other hand you can override onConfigurationChanged method every time app is rotated this method will run, so you can use it to set your data.
#Override
public void onConfigurationChanged(#NonNull Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
Please check whether both of your CustomTextWithSwitch and its children on Activity has android:ids. Ids should be different. In this case Android take care about saving instance state for your view.
If it does not save your state, use this code inside your CustomTextWithSwitch
#Override
public Parcelable onSaveInstanceState()
{
Bundle bundle = new Bundle();
bundle.putParcelable("superState", super.onSaveInstanceState());
bundle.putBoolean("isChecked", defaultValue); // ... save check state
return bundle;
}
#Override
public void onRestoreInstanceState(Parcelable state)
{
if (state instanceof Bundle)
{
Bundle bundle = (Bundle) state;
defaultValue = bundle.getBoolean("isChecked"); // ... load state
binding.sToggle.setChecked(defaultValue);
state = bundle.getParcelable("superState");
}
super.onRestoreInstanceState(state);
}
Have faced the same issue. I fixed it by setting setSaveEnabled(false) on the switch view. Just let the viewModel restore it's state.
public CustomTextWithSwitch(Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
binding = CustomTextWithSwitchBinding.inflate(LayoutInflater.from(getContext()), this);
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CustomTextWithSwitch);
defaultValue = a.getBoolean(R.styleable.CustomTextWithSwitch_defaultValue, false);
a.recycle();
//Add this (assuming your switch view id is 'switch_view')
binding.switchView.setSaveEnabled(false);
}

Handling long values on custom preferences

I created a custom Preference for my Android App, a number-picker preference to be exact. It's really a shame that Android don't provide already a built-in preference for that, but we need to deal with it so I created one and since I could re-use that code in future projects I decided to make it using long values, so it could handle very large numbers, but I found something very curious.
You can store long values on the SharedPreferences but there isn't any getLong() on a TypedArray which is used to access attribute values on Android. So the work-around that I made was to get the values from the TypedArray as Strings and convert them to long. But I'm wondering if there is a better approach
Here I leave you the code snippet, feel free to use it in your projects, it's not using the NumberPicker Widget, it's built with a TextView and two buttons so you can use it on old devices.
public class NumberPickerPreference extends DialogPreference {
private long max;
private long min;
private long value;
private TextView picker;
private Button btnUp;
private Button btnDown;
private int step;
private long defValue;
public NumberPickerPreference(Context context, AttributeSet attrs) {
super(context, attrs);
setPersistent(false);
setDialogLayoutResource(R.layout.number_picker);
setPositiveButtonText(android.R.string.ok);
setNegativeButtonText(R.string.cancel);
TypedArray numberPickerType=context.obtainStyledAttributes(attrs,
R.styleable.NumberPickerPreference, 0, 0);
String maxStr = numberPickerType.getString(R.styleable.NumberPickerPreference_max);
if(maxStr==null) {
maxStr="50";
}
String minStr=numberPickerType.getString(R.styleable.NumberPickerPreference_min);
if(minStr==null) {
minStr="5";
}
step=numberPickerType.getInt(R.styleable.NumberPickerPreference_step, 1);
max=Long.parseLong(maxStr);
min=Long.parseLong(minStr);
numberPickerType.recycle();
}
#Override
protected void onBindDialogView(View v) {
picker=(TextView)v.findViewById(R.id.tvNumUpDown);
btnUp=(Button)v.findViewById(R.id.btnUp);
btnDown=(Button)v.findViewById(R.id.btnDown);
btnUp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
add();
}
});
btnDown.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
subs();
}
});
value=getSharedPreferences().getLong(getKey(), defValue);
picker.setText(value+"");
super.onBindDialogView(v);
}
#Override
protected void onSetInitialValue(boolean restorePersistedValue,
Object defaultValue) {
long aux=min;
if(defaultValue!=null && !defaultValue.toString().isEmpty()) {
aux=Long.parseLong(defaultValue.toString());
}
defValue=(restorePersistedValue?getPersistedLong(min):aux);
}
/**
* You can provide a default value with the android:defaultValue attribute here
*/
#Override
protected Object onGetDefaultValue(TypedArray a, int index) {
return a.getString(index);
}
protected void subs() {
if(value>min) {
value-=step;
picker.setText(value+"");
}
}
protected void add() {
if(value<max) {
value+=step;
picker.setText(value+"");
}
}
#Override
protected void onDialogClosed(boolean positiveResult) {
if(positiveResult) {
getEditor().putLong(getKey(), value).commit();
}
}
}
This is quite an old question, but I will give an answer for the benefit of future readers.
Converting from a String as you have done here is a fine approach. Ultimately that is what DialogPreference would be doing anyway. The attribute in XML is a String, so whether you convert it, or it is converted for you, the data will be coming from a parsed String. Just ensure when you are making the conversion you handle invalid data / NumberFormatExceptions properly.

Android : Form Validation Library

I am trying to find a form validation library in android. Is there such a thing ?
I have a registration form that I want to validate its fields. If the user enters an invalid data, I want to put a red warning mark at the right of the field and pop up a tooltip that he entered an invalid data.
I know about the android:inputType but this is not what I want
I don't know about any such libraries. But if you are working with EditTexts, then your best option is to use a custom TextWatcher:
class TextCheck implements TextWatcher
{
private EditText editor;
public TextCheck(EditText editor)
{
this.editor = editor;
}
#Override
public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3)
{
// check the text, and if the user entered
// something wrong, change your edittext
if(something wrong)
{
editor.setBackgroundColor(Color.RED); //for example
}
}
#Override
public void afterTextChanged(Editable arg0){}
#Override
public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3){}
}
And then you can use it on all your EditTexts like
EditText editor = (EditText) findViewById(...your id...);
editor.addTextChangedListener(new TextCheck(editor));
Is there such a thing?
Ah.. yes there is one and you can find it here.
It does form validation for you, using but not limited to Annotations. To find out what the library does please visit the following answer on SO where I have described the usage of the library.
If you want to write new rules you can always extend the Rule class.
PS: I am the author of the library.
I know this is old, but you can try this excellent Android Validation library and visit this Stackoverflow reference and this Stackoverflow reference for usage examples because I found the main librarys how-tos kinda of hard to understand.
I did something similar. You can improve this code and adapt for your necessity.
EditTextWithValidation.java
public class EditTextWithValidation extends EditText implements OnTouchListener {
private EditTextValidator mValidator;
public EditTextWithValidation(Context context) {
super(context);
initialize();
}
public EditTextWithValidation(Context context, AttributeSet attrs) {
super(context, attrs);
initialize();
}
public EditTextWithValidation(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initialize();
}
public EditTextValidator getCustomValidator() {
return mValidator;
}
#Override
public boolean onTouch(View v, MotionEvent event) {
setError(null);
return false;
}
private void initialize() {
mValidator = new EditTextValidator(this);
setOnTouchListener(this);
}
}
EditTextValidator.java
public class EditTextValidator {
private static final String TAG = EditTextValidator.class.getName();
private enum ValidationResult {
Ok, Rules, Mismatch
}
private EditText mParent;
private Pattern mValidationPattern;
private int mValidationErrorMsgId;
private boolean mAllowEmpty;
private EditText mMatchView;
private int mMismatchMsgId;
private int mMinLength;
private int mMaxLength;
private ValidationResult mValidationResult;
public EditTextValidator(EditText parent) {
this.mParent = parent;
}
public void setAllowEmpty(boolean allowEmpty) {
this.mAllowEmpty = allowEmpty;
}
public void setValidationErrorMsgId(int validationErrorMsgId) {
this.mValidationErrorMsgId = validationErrorMsgId;
}
public void setValidationRules(String strPattern, int validationErrorMsgId, boolean allowEmpty) {
try {
if (!TextUtils.isEmpty(strPattern)) {
mValidationPattern = Pattern.compile(strPattern);
}
} catch (PatternSyntaxException e) {
Log.e(TAG, e.getMessage(), e);
ToastUtil.toastShort("Invalid validation pattern!");
}
this.mValidationErrorMsgId = validationErrorMsgId;
this.mAllowEmpty = allowEmpty;
}
public void setValidLength(int min, int max) {
mMinLength = min;
mMaxLength = max;
}
public void shouldMatch(EditText matchView, int mismatchMsgId) {
this.mMatchView = matchView;
this.mMismatchMsgId = mismatchMsgId;
}
public boolean validate() {
mValidationResult = ValidationResult.Ok;
InputMethodManager imm = (InputMethodManager) mParent.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(mParent.getWindowToken(), 0);
final String text = mParent.getText().toString();
final int length = text.length();
if (mValidationResult == ValidationResult.Ok && !mAllowEmpty && 0 == text.length()) {
mValidationResult = ValidationResult.Rules;
}
if (mValidationResult == ValidationResult.Ok) {
if (mMinLength != 0 && length < mMinLength) {
mValidationResult = ValidationResult.Rules;
} else if (mMaxLength != 0 && length > mMaxLength) {
mValidationResult = ValidationResult.Rules;
}
}
if (mValidationResult == ValidationResult.Ok && mValidationPattern != null) {
Matcher m = mValidationPattern.matcher(text);
if (!m.matches())
mValidationResult = ValidationResult.Rules;
}
if (mValidationResult == ValidationResult.Ok && mMatchView != null) {
if (mMatchView.getText().toString().compareTo(text) != 0)
mValidationResult = ValidationResult.Mismatch;
}
if (ValidationResult.Ok == mValidationResult) {
mParent.setError(null);
} else {
CharSequence error = null;
if (ValidationResult.Rules == mValidationResult)
error = MyApplication.getContext().getText(mValidationErrorMsgId);
else if (ValidationResult.Mismatch == mValidationResult)
error = MyApplication.getContext().getText(mMismatchMsgId);
mParent.setError(error);
mParent.requestFocus();
}
return mValidationResult == ValidationResult.Ok;
}
}
Usage:
mSignupEmail = (EditTextWithValidation) root.findViewById(R.id.signup_email);
mSignupEmail.getCustomValidator().setValidationRules(
"[a-zA-Z0-9_-]+(?:\\.[a-zA-Z0-9_-]+)*#[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9_-]+)*\\.(?:[a-zA-Z]{2,})",
R.string.email_answer_validation_msg,
false);
mSignupEmail.getCustomValidator().setValidLength(0, 50);
…
mSignupPassword = (EditTextWithValidation) root.findViewById(R.id.signup_password);
mSignupPassword.getCustomValidator().setValidationRules(
"[a-zA-Z0-9!##$%^&*()]{6,20}",
R.string.password_validation_msg,
false);
…
mSignupConfirmPassword = (EditTextWithValidation) root.findViewById(R.id.signup_confirm_password);
mSignupConfirmPassword.getCustomValidator().setAllowEmpty(true);
mSignupConfirmPassword.getCustomValidator().shouldMatch(mSignupPassword, R.string.password_mismatch);
mSignupConfirmPassword.getCustomValidator().setValidationErrorMsgId(R.string.password_validation_msg);
…
if (mSignupEmail.getCustomValidator().validate() && mSignupPassword.getCustomValidator().validate() && mSignupConfirmPassword.getCustomValidator().validate()) {
// DO SOMETHING
}
Install this app: https://play.google.com/store/apps/details?id=com.desarrollodroide.repos
Go to: Utils -> Android-Validator -> View Demo
There are a bunch of other cool libraries in this app as well. The good thing is that you can view demo of each library and get the link to github repo of that particular library if you like it. It's very useful.

Android TimePicker in PreferenceScreen -> read the values

I have a custom DialogPreference. The Dialog is called from a PreferenceScreen.
All works fine, the Dialog starts and shows the TimePicker.
But how do I get the selected values?
First of all, I tried to write the selected hours in the summary of the Preference. (therefore the var xxx :)
Later on, I want to save the values in SharedPreferences.
This is what I have for now:
public class Calendar extends DialogPreference implements
TimePicker.OnTimeChangedListener {
TimePicker tp;
int xxx;
public Calendar(Context context, AttributeSet attrs) {
super(context, attrs);
initialize();
}
public Calendar(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initialize();
}
private void initialize() {
setPersistent(true);
}
#Override
protected View onCreateDialogView() {
tp = new TimePicker(getContext());
tp.setIs24HourView(true);
return tp;
}
#Override
public void onTimeChanged(TimePicker arg0, int arg1, int arg2) {
}
#Override
public void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult) {
// getEditor().
setTitle(getTitle());
setSummary(Integer.toString(xxx));
}
}
private TimePicker.OnTimeChangedListener mTimeSetListener =
new TimePicker.OnTimeChangedListener() {
#Override
public void onTimeChanged(TimePicker view, int hourOfDay, int minute) {
xxx=hourOfDay;
}
};
}
Thanks a lot and best regards
Thanks for asking this question, it provided me with an important answer on how to create a DialogPreference.
I hope I might also have an answer for you. I modified your code a little bit and I can now store the time selected from the Dialog:
#Override
protected View onCreateDialogView() {
this.tp = new TimePicker(getContext());
this.tp.setIs24HourView(true);
final String storedValue = getPersistedString("07:00");
final String[] split = storedValue.split(":");
this.tp.setCurrentHour(Integer.parseInt(split[0]));
this.tp.setCurrentMinute(Integer.parseInt(split[1]));
return this.tp;
}
#Override
public void onDialogClosed(boolean positiveResult) {
super.onDialogClosed(positiveResult);
if (positiveResult) {
final String result = this.tp.getCurrentHour() + ":" + this.tp.getCurrentMinute();
persistString(result);
}
}
When the dialog is shown I retrieve the stored value and simply set the currentHour and currentMinute fields of the TimePicker. The other way round when the dialog is closed. Since I control both the format on the way in as well as on the way out there should not be a problem with illegal values.
Was this what you were looking for?
To store the value in shared pref, implement on preference Change Listener.
note that preference should be default Shared preference
preferences = PreferenceManager.getDefaultSharedPreferences(context);
editor = preferences.edit();
inside onprefchange:
if (preference.getKey().equals(getString(R.string.reminder_end_time_key))){
editor.putString("End_Date", String.valueOf(newValue));
editor.apply();
endTimePickerPreference.setSummary((CharSequence)newValue);
}

PreferenceActivity: save value as integer

Using a simple EditTextPreference in my preferences activity:
<EditTextPreference
android:key="SomeKey"
android:title="#string/some_title"
android:summary="..."
android:numeric="integer"
android:maxLength="2"
/>
Is there a way that this configuration value would be saved as integer? Seems now it just allows to enter numbers, but the value is still saved as string:
Calling:
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
int value = preferences.getInt("SomeKey", -1);
throws me java.lang.ClassCastException: java.lang.String, and:
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
String value = preferences.getString("SomeKey", "-1");
retrieves the value successfully.
How to make PreferenceActivity to save value as integer by default?
You could extend EditTextPreference:
public class IntEditTextPreference extends EditTextPreference {
public IntEditTextPreference(Context context) {
super(context);
}
public IntEditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
}
public IntEditTextPreference(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected String getPersistedString(String defaultReturnValue) {
return String.valueOf(getPersistedInt(-1));
}
#Override
protected boolean persistString(String value) {
return persistInt(Integer.valueOf(value));
}
}
It would be better to overwrite onSetInitialValue() and setText() methods, but then you would have to copy some code from a base class. Above solution is simplier, but it's quite tricky - "string" methods do something with ints. Try to not extend this class further ;-)
You could use it from XML by:
<package.name.IntEditTextPreference
android:key="SomeKey"
android:title="#string/some_title"
android:summary="..."
android:numeric="integer"
android:maxLength="2"
/>
Even if you set android:numeric="integer" it'll be text preference - as its name suggest. You could easily convert string value to int using Integer.valueOf(). Also you could overwrite PreferenceActivity to do conversion automatically on exit.
I think the best solution is to write simple method to get this value from preferences. Something like:
public static int getSomePref(Context context) {
SharedPreferences prefs =
PreferenceManager.getDefaultSharedPreferences(context);
String value = prefs.getString("SomeKey", null);
return value == null ? -1 : Integer.valueOf(value);
}
Then you could very easily use it from your code.
Even though an Answer has been parked accepted I would like to share one more shorter way to achieve this :
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
int value = Integer.parseInt(preferences.getString("SomeKey", "-1"));
Since you have already set that only numbers can be entered this won't through any exception.
yet to complete my answer :
<EditTextPref
android:key="SomeKey"
android:title="#string/some_title"
android:summary="..."
android:numeric="integer"
android:maxLength="2" />
I know this is an old question with an already accepted answer but I think my solution can be helpful for someone searching for a more complete answer. I have just improved #broot answer a litte and there goes my solution:
Override the EditTextPreference to provide text to int conversion:
public class IntEditTextPreference extends EditTextPreference implements EditTextPreference.OnBindEditTextListener {
private String mText;
public IntEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
setOnBindEditTextListener(this);
}
public IntEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setOnBindEditTextListener(this);
}
public IntEditTextPreference(Context context, AttributeSet attrs) {
super(context, attrs);
setOnBindEditTextListener(this);
}
public IntEditTextPreference(Context context) {
super(context);
setOnBindEditTextListener(this);
}
/**
* Saves the text to the current data storage.
*
* #param text The text to save
*/
public void setText(String text) {
final boolean wasBlocking = shouldDisableDependents();
mText = text;
int value = Integer.parseInt(text);
persistInt(value);
final boolean isBlocking = shouldDisableDependents();
if (isBlocking != wasBlocking) {
notifyDependencyChange(isBlocking);
}
notifyChanged();
}
/**
* Gets the text from the current data storage.
*
* #return The current preference value
*/
public String getText() {
return mText;
}
#Override
protected void onSetInitialValue(Object defaultValue) {
int value;
if (defaultValue != null) {
String strDefaultValue = (String) defaultValue;
int defaultIntValue = Integer.parseInt(strDefaultValue);
value = getPersistedInt(defaultIntValue);
} else {
value = getPersistedInt(0);
}
setText(Integer.toString(value));
}
#Override
public boolean shouldDisableDependents() {
return TextUtils.isEmpty(mText) || super.shouldDisableDependents();
}
#Override
public void onBindEditText(#NonNull EditText editText) {
editText.setInputType(InputType.TYPE_CLASS_NUMBER);
}
}
In the preferences xml:
<your.package.here.IntEditTextPreference
android:key="some_key"
android:title="#string/some_title"
android:defaultValue="5"
app:useSimpleSummaryProvider="true"/>
Note: Don't use android:numeric nor android:inputType. Since EditTextPreference is not an EditText itself setting those attributes will do nothing. In order to achieve the desired effect on the EditText from the Dialog opened by the EditTextPreference, just set the input type in your custom EditTextPreference by implementing EditTextPreference.OnBindEditTextListener as you can see in the code above.
That's what worked for me.
I had the same Problem. (I wanted SharedPreference to give me a port number that i stored in a preferences xml file as defaultValue).
Implementing all the SharedPreferences methods would be much effort, so writing a custom method in the class that instanced the SharedPreferences, as broot suggested would be best i think.
You can aswell just use the Static method of Integer in the line where you need it:
int number = Integer.valueOf(settings.getString("myNumberString", "0"));
I think this is the shortest one I could come up with:
int CheckInterval = Integer.parseInt(sharedPreferences.getString("check_frequency","60"));

Categories

Resources