Created
November 8, 2012 08:00
-
-
Save granoeste/4037468 to your computer and use it in GitHub Desktop.
[Android] To implement state saving and restoration in the custom view.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// To implement state saving and restoration in the custom view... | |
// | |
// You should implement the SavedState extend the BaseSavedState. | |
// You should be implemented to override the onSaveInstanceState and onRestoreInstanceState. | |
// TextView will be helpful. | |
// TextView | |
public class TextView extends View implements ViewTreeObserver.OnPreDrawListener { | |
/** | |
* User interface state that is stored by TextView for implementing | |
* {@link View#onSaveInstanceState}. | |
*/ | |
public static class SavedState extends BaseSavedState { | |
int selStart; | |
int selEnd; | |
CharSequence text; | |
boolean frozenWithFocus; | |
CharSequence error; | |
SavedState(Parcelable superState) { | |
super(superState); | |
} | |
@Override | |
public void writeToParcel(Parcel out, int flags) { | |
super.writeToParcel(out, flags); | |
out.writeInt(selStart); | |
out.writeInt(selEnd); | |
out.writeInt(frozenWithFocus ? 1 : 0); | |
TextUtils.writeToParcel(text, out, flags); | |
if (error == null) { | |
out.writeInt(0); | |
} else { | |
out.writeInt(1); | |
TextUtils.writeToParcel(error, out, flags); | |
} | |
} | |
@Override | |
public String toString() { | |
String str = "TextView.SavedState{" | |
+ Integer.toHexString(System.identityHashCode(this)) | |
+ " start=" + selStart + " end=" + selEnd; | |
if (text != null) { | |
str += " text=" + text; | |
} | |
return str + "}"; | |
} | |
@SuppressWarnings("hiding") | |
public static final Parcelable.Creator<SavedState> CREATOR | |
= new Parcelable.Creator<SavedState>() { | |
public SavedState createFromParcel(Parcel in) { | |
return new SavedState(in); | |
} | |
public SavedState[] newArray(int size) { | |
return new SavedState[size]; | |
} | |
}; | |
private SavedState(Parcel in) { | |
super(in); | |
selStart = in.readInt(); | |
selEnd = in.readInt(); | |
frozenWithFocus = (in.readInt() != 0); | |
text = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); | |
if (in.readInt() != 0) { | |
error = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in); | |
} | |
} | |
} | |
@Override | |
public Parcelable onSaveInstanceState() { | |
Parcelable superState = super.onSaveInstanceState(); | |
// Save state if we are forced to | |
boolean save = mFreezesText; | |
int start = 0; | |
int end = 0; | |
if (mText != null) { | |
start = getSelectionStart(); | |
end = getSelectionEnd(); | |
if (start >= 0 || end >= 0) { | |
// Or save state if there is a selection | |
save = true; | |
} | |
} | |
if (save) { | |
SavedState ss = new SavedState(superState); | |
// XXX Should also save the current scroll position! | |
ss.selStart = start; | |
ss.selEnd = end; | |
if (mText instanceof Spanned) { | |
/* | |
* Calling setText() strips off any ChangeWatchers; | |
* strip them now to avoid leaking references. | |
* But do it to a copy so that if there are any | |
* further changes to the text of this view, it | |
* won't get into an inconsistent state. | |
*/ | |
Spannable sp = new SpannableString(mText); | |
for (ChangeWatcher cw : sp.getSpans(0, sp.length(), ChangeWatcher.class)) { | |
sp.removeSpan(cw); | |
} | |
removeMisspelledSpans(sp); | |
sp.removeSpan(mSuggestionRangeSpan); | |
ss.text = sp; | |
} else { | |
ss.text = mText.toString(); | |
} | |
if (isFocused() && start >= 0 && end >= 0) { | |
ss.frozenWithFocus = true; | |
} | |
ss.error = mError; | |
return ss; | |
} | |
return superState; | |
} | |
@Override | |
public void onRestoreInstanceState(Parcelable state) { | |
if (!(state instanceof SavedState)) { | |
super.onRestoreInstanceState(state); | |
return; | |
} | |
SavedState ss = (SavedState)state; | |
super.onRestoreInstanceState(ss.getSuperState()); | |
// XXX restore buffer type too, as well as lots of other stuff | |
if (ss.text != null) { | |
setText(ss.text); | |
} | |
if (ss.selStart >= 0 && ss.selEnd >= 0) { | |
if (mText instanceof Spannable) { | |
int len = mText.length(); | |
if (ss.selStart > len || ss.selEnd > len) { | |
String restored = ""; | |
if (ss.text != null) { | |
restored = "(restored) "; | |
} | |
Log.e(LOG_TAG, "Saved cursor position " + ss.selStart + | |
"/" + ss.selEnd + " out of range for " + restored + | |
"text " + mText); | |
} else { | |
Selection.setSelection((Spannable) mText, ss.selStart, | |
ss.selEnd); | |
if (ss.frozenWithFocus) { | |
mFrozenWithFocus = true; | |
} | |
} | |
} | |
} | |
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); | |
} | |
}); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment