【问题标题】:EditText saved the value after device rotation automaticallyEditText 自动保存设备旋转后的值
【发布时间】:2018-01-21 08:32:08
【问题描述】:

我在 Android Studio 中创建了一个示例应用程序来了解 Android 应用程序的生命周期。我知道方向更改会完全重新启动活动(即再次调用 OnCreate 方法)。 据我所知,方向更改应该破坏了上下文并在设备旋转后显示空白文本。但不知何故,在不覆盖 onSaveInstanceState 和 onRestoreInstanceState 方法的情况下,它正在保存上下文。

我没有任何碎片。它只是 Android Studio 提供的基本模板,几乎没有覆盖生命周期方法。 这是我的 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");
    }
}

布局:

<?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:

<?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>

图片:

【问题讨论】:

  • EditTexts 自动保存/恢复已保存状态包中的文本。你不需要做任何事情来让它发生。 developer.android.com/reference/android/widget/…(请注意,“冰柱”是已保存状态包的旧术语。)
  • 轻微修正:EditTexts 具有唯一 ID 将自动保存其文本。
  • @SreekanthKarumanaghat 我不能说为什么设计师决定让EditText 表现得那样,但我猜这只是因为它使开发人员的工作更容易一些,而不必跟踪每个外部修改的文本。其他Views 可以保存和恢复状态,如果它们被配置为这样的话。任何包含带有 ID 的 EditText 的内容都将保存其文本;例如,SearchView。此外,ListView 将保存它的滚动位置,ViewPager 将保存它的当前项目索引,DrawerLayout 将保存它的抽屉状态(虽然只有一个抽屉),等等。
  • @SreekanthKarumanaghat 您可以将它们用于您需要类似保存/恢复的任何东西,这些东西不是由Views 或框架固有地跟踪的。真的没有完整的清单或任何东西,坦率地说,也不可能。我想这只是当你对一切变得更加熟悉时才知道的。想到的第一件事,虽然它与View 无关,但当您可以动态创建Uri 以传递ACTION_IMAGE_CAPTURE Intent 时,您需要保存它以防您的@ 987654341@在相机应用打开时被临时销毁。
  • @SreekanthKarumanaghat 我不太确定你在问什么。此外,所有这些都更适合作为一个全新的问题,而不是在旧帖子上的 cmets 中进行讨论。我们真的不应该在这里进行长时间的对话。请随时就您的疑虑发布一个新问题。干杯!

标签: java android android-edittext orientation


【解决方案1】:

因为EditText 是一个焦点视图,所以在PhoneWindow 中,它的状态会自动保存在saveHierarchyState() 方法中。可以看代码:

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

以及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;
}

因此,如果您在 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>

你会看到你想要的! (来自@Mike M 的补充坦克。)

【讨论】:

【解决方案2】:

Android默认是恢复部分View的状态。 在您的 Layout xml 中,将 android:saveEnabled="false" 添加到您的 EditText。并且EditText的值不会被保留。

【讨论】:

  • 我看到了一些教程,其中在方向更改后文本丢失了。此默认行为是否已添加到较新版本的 Android 中?
  • 根据 Android 参考,这种行为似乎与默认值没有改变。但是如果要刷新(清除)View的数据,则必须将此属性设置为false。 developer.android.com/reference/android/R.attr.html#saveEnabled
  • @LakshmikantDeshpande 如果您没有为编辑文本指定 id,则不会保留该值。
【解决方案3】:

Android 会自动处理保存状态和恢复,直到您明确指定

android:configChanges="orientation"

在你的主文件中

如果您没有 ui 元素的id,Android 将无法恢复该元素的状态。

请参考这里的答案 https://stackoverflow.com/a/19234974/1099156

【讨论】:

  • 我在清单中指定了 android:configChanges="orientation" ,并且仍然在旋转时编辑文本保留了这些值。从我的清单中截取的是
猜你喜欢
  • 1970-01-01
  • 2011-03-16
  • 1970-01-01
  • 2014-08-27
  • 2014-08-20
  • 2021-05-27
  • 2011-02-26
  • 1970-01-01
  • 2017-05-29
相关资源
最近更新 更多