简体   繁体   English

EditText 自动保存设备旋转后的值

[英]EditText saved the value after device rotation automatically

I created a sample application in Android Studio to learn about the life cycle of an Android application.我在 Android Studio 中创建了一个示例应用程序来了解一个 Android 应用程序的生命周期。 I know that orientation change completely restarts the activity (ie OnCreate method is called again).我知道方向更改会完全重新启动活动(即再次调用 OnCreate 方法)。 As far as I know, orientation change should have destroyed the context and shown a blank text after device rotation.据我所知,方向更改应该会破坏上下文并在设备旋转后显示空白文本。 But somehow without overriding onSaveInstanceState and onRestoreInstanceState methods it is saving the context.但不知何故,它在不覆盖 onSaveInstanceState 和 onRestoreInstanceState 方法的情况下保存了上下文。

I don't have any fragments.我没有任何碎片。 It just the basic template that is provided by Android studio, with few overridden life cycle methods.它只是 Android Studio 提供的基本模板,几乎没有被覆盖的生命周期方法。 Here is my MainActivity class:这是我的 MainActivity 类:

package com.example.android.a2_screen_orientation_change;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

    private static final String TAG = MainActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.i(TAG, "in method onStart");
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.i(TAG, "in method onResume");
    }

    @Override
    protected void onRestart() {
        super.onRestart();
        Log.i(TAG, "in method onRestart");
    }

    @Override
    protected void onPause() {
        super.onPause();
        Log.i(TAG, "in method onPause");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.i(TAG, "in method onStop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "in method onDestroy");
    }
}

Layout:布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.android.a2_screen_orientation_change.MainActivity">

    <EditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

AbdroidManifest: AbdroidManifest:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.android.a2_screen_orientation_change">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Image:图片: 即使在设备方向更改后文本也会被保存

Because the EditText is a focused view, so in PhoneWindow , it's state will be saved automatically in saveHierarchyState() method.因为 EditText 是一个焦点视图,所以在PhoneWindow ,它的状态将在saveHierarchyState()方法中自动保存。 You can see the code:你可以看到代码:

@Override
public Bundle saveHierarchyState() {
    Bundle outState = new Bundle();
    if (mContentParent == null) {
        return outState;
    }
    SparseArray<Parcelable> states = new SparseArray<Parcelable>();
    mContentParent.saveHierarchyState(states);
    outState.putSparseParcelableArray(VIEWS_TAG, states);
    // save the focused view id
    View focusedView = mContentParent.findFocus();
    if (focusedView != null) {
        if (focusedView.getId() != View.NO_ID) {
            outState.putInt(FOCUSED_ID_TAG, focusedView.getId());
        } else {
            if (false) {
                Log.d(TAG, "couldn't save which view has focus because the focused view "
                        + focusedView + " has no id.");
            }
        }
    }
    // save the panels
    SparseArray<Parcelable> panelStates = new SparseArray<Parcelable>();
    savePanelState(panelStates);
    if (panelStates.size() > 0) {
        outState.putSparseParcelableArray(PANELS_TAG, panelStates);
    }
    if (mActionBar != null) {
        outState.putBoolean(ACTION_BAR_TAG, mActionBar.isOverflowMenuShowing());
    }
    return outState;
}

and the code in TextView :TextView的代码:

@Override
public Parcelable onSaveInstanceState() {
    Parcelable superState = super.onSaveInstanceState();
    // Save state if we are forced to
    final boolean freezesText = getFreezesText();
    boolean hasSelection = false;
    int start = -1;
    int end = -1;
    if (mText != null) {
        start = getSelectionStart();
        end = getSelectionEnd();
        if (start >= 0 || end >= 0) {
            // Or save state if there is a selection
            hasSelection = true;
        }
    }
    if (freezesText || hasSelection) {
        SavedState ss = new SavedState(superState);
        if (freezesText) {
            if (mText instanceof Spanned) {
                final Spannable sp = new SpannableStringBuilder(mText);
                if (mEditor != null) {
                    removeMisspelledSpans(sp);
                    sp.removeSpan(mEditor.mSuggestionRangeSpan);
                }
                ss.text = sp;
            } else {
                ss.text = mText.toString();
            }
        }
        if (hasSelection) {
            // XXX Should also save the current scroll position!
            ss.selStart = start;
            ss.selEnd = end;
        }
        if (isFocused() && start >= 0 && end >= 0) {
            ss.frozenWithFocus = true;
        }
        ss.error = getError();
        if (mEditor != null) {
            ss.editorState = mEditor.saveInstanceState();
        }
        return ss;
    }
    return superState;
}

So, if you remove the id of the EditTextView in your xml file:因此,如果您删除 xml 文件中 EditTextView 的 id:

    <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.android.a2_screen_orientation_change.MainActivity">

    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

</LinearLayout>

You will see what you want!你会看到你想要的! (Tanks for supplement from @Mike M.) (来自@Mike M. 的补充罐)

Android is by default, restoring the state of some Views. Android 是默认的,恢复一些视图的状态。 In your Layout xml, add android:saveEnabled="false" to your EditText.在您的布局 xml 中,将android:saveEnabled="false"到您的 EditText。 And the value of EditText will not be retained.并且不会保留 EditText 的值。

Android automatically handles saving the state & restoring until you explicitly specify the Android 会自动处理保存状态和恢复状态,直到您明确指定

android:configChanges="orientation"

in your mainifest在你的主播中

In case, you do not have an id for the ui element, Android will not be able to restore the state of the element.如果您没有 ui 元素的id ,Android 将无法恢复该元素的状态。

Please refer to the answer here https://stackoverflow.com/a/19234974/1099156请参考这里的答案https://stackoverflow.com/a/19234974/1099156

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM