How EditText Retains its value but not textview when phone orientation changes?

社会主义新天地 提交于 2019-12-23 07:51:18

问题


What is so special about Edittext that it can retain the value but not Textview and some other widgets and we have to use onSavedInstance() method for them.

What is the magic behind EditText specially that it can retain the values?

If someone can tell how it works internally.

<----Update---->

How it works internally, Please point to that part of the code which explains this scenario.


回答1:


What is the magic behind EditText specially that it can retain the values? How it works internally, Please point to that part of the code which explains this scenario.

It is the selectable property which brings the difference. The following if condition in TextView.onSaveInstanceState takes care of it.

@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;
        }
    }

    ...
}

By default TextView can't be selected. Hence getSelectionStart() and getSelectionEnd() returns -1, there by save variable holds false value. To make it retain it's content on orientation change, set the attribute textIsSelectable to true.

Since EditText is selectable by default, getSelectionStart() and getSelectionEnd() always return value >=0, there by save variable holds true value and the content gets saved.

Note : By default freezesText is disabled. Hence mFreezesText value is false.




回答2:


Quoting from this article:https://tekeye.uk/android/examples/saving-activity-state

"Switching the device from portrait to landscape causes Android to stop and restart the Activity, allowing Activities the opportunity to redraw a screen for the different dimensions. With stopping and starting an Activity a common occurrence users would be annoyed if input kept being lost. Android activites have a pair of methods called onSaveInstanceState(Bundle) and onRestoreInstanceState(Bundle) which are automatically used by input Views to save their data. These methods only work if the Views that take data can be identified, hence the need for the EditText (and all screen items) to have an id. A bonus is that this method pair can be overridden in an Activity so that state variables not associated with input fields can also be saved and restored."

Remove the id from an edittext and try it :)




回答3:


By default, EditText view saves its state - This is accomplished by setting flags in code telling the view to save state when view is not visible or lost focus. The text is automatically saved and restored after rotating device. The automatic saving of state of EditText view can be disabled in the XML layout file by setting the android:saveEnabled property to false:

 android:saveEnabled="false"

Or programmatically, call view.setSaveEnabled(false).

saveEnabled controls whether the saving of this view's state is enabled (that is, whether its onSaveInstanceState() method will be called). Note that even if freezing is enabled, the view still must have an id assigned to it (via setId()) for its state to be saved. This flag can only disable the saving of this view; any child views may still have their state saved. saveEnabled attribute is part of android View - View Code. Here is related parts of code:

public boolean isSaveEnabled() {
        return (mViewFlags & SAVE_DISABLED_MASK) != SAVE_DISABLED;
    }

...

 public void setSaveEnabled(boolean enabled) {
        setFlags(enabled ? 0 : SAVE_DISABLED, SAVE_DISABLED_MASK);
    }

...

 void setFlags(int flags, int mask) {
        int old = mViewFlags;
        mViewFlags = (mViewFlags & ~mask) | (flags & mask);

        int changed = mViewFlags ^ old;
        if (changed == 0) {
            return;
        }
        int privateFlags = mPrivateFlags;

        /* Check if the FOCUSABLE bit has changed */
        if (((changed & FOCUSABLE_MASK) != 0) &&
                ((privateFlags & HAS_BOUNDS) !=0)) {
            if (((old & FOCUSABLE_MASK) == FOCUSABLE)
                    && ((privateFlags & FOCUSED) != 0)) {
                /* Give up focus if we are no longer focusable */
                clearFocus();
            } else if (((old & FOCUSABLE_MASK) == NOT_FOCUSABLE)
                    && ((privateFlags & FOCUSED) == 0)) {
                /*
                 * Tell the view system that we are now available to take focus
                 * if no one else already has it.
                 */
                if (mParent != null) mParent.focusableViewAvailable(this);
            }
        }

....




回答4:


Try this for your textview I think it may help you

<TextView 
 ... 
 android:freezesText="true" />



回答5:


Android View class have protected methods

protected Parcelable onSaveInstanceState ()
protected void onRestoreInstanceState (Parcelable state)

so any view can override those methods and save View's state information with them.

TextView extends View class and have implementation of protected Parcelable onSaveInstanceState() and protected void onRestoreInstanceState (Parcelable state) within it.

lets look at implementation of onSaveInstanceState()

@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;
        }
    }
    ...
}
  1. as you can see here save feature is depending on single flag "save" so if user explicitly specify mFreezesText = true then it will save the text
  2. another possiblity if there is selection cursor then it will at least return getSelectionStart() = 0 and not -1 that will cause TextView to make save=true to save state of TextView and thats what happening with EditText as EditText have selection cursor and it does extends TextView.


来源:https://stackoverflow.com/questions/15545211/how-edittext-retains-its-value-but-not-textview-when-phone-orientation-changes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!