Android 8.0 Oreo在聚焦TextInputEditText时崩溃

105

在升级我们的一些设备到Android 8.0之后,在TextInputLayout中聚焦于TextInputEditText字段时,应用程序会崩溃并出现以下Exception

Fatal Exception: java.lang.NullPointerException: Attempt to invoke virtual method 'void
android.view.View.getBoundsOnScreen(android.graphics.Rect)' on a null object reference
at android.app.assist.AssistStructure$WindowNode.(AssistStructure.java)
at android.app.assist.AssistStructure.(AssistStructure.java)
at android.app.ActivityThread.handleRequestAssistContextExtras(ActivityThread.java:3035)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1807)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:164)
at android.app.ActivityThread.main(ActivityThread.java:6541)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:240)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:767)

当我们进入Android的设置 -> 系统 -> 语言和输入法 -> 高级选项 -> 自动填充服务 -> 无后,将焦点放在TextInputEditText/TextInputLayout上,就不再会崩溃。

如何在不禁用设备上的新8.0自动填充服务的情况下防止崩溃发生?


6
https://issuetracker.google.com/issues/62834931 - Mike M.
8个回答

193

我也遇到过这个问题。原来是在 TextInputLayout 内部嵌套的 EditText 上设置提示文本引起的。

我找到了一些信息,发现在 26.0.0 Beta 2 版本中有这样一条提示。 Android 支持库-2017年6月版本更新日志

TextInputLayout 必须在 onProvideAutofillStructure() 上设置提示信息

这让我尝试在 TextInputLayout 上设置提示文本,而不是在内部的 EditText 上。

这解决了我遇到的崩溃问题。例如:

<android.support.design.widget.TextInputLayout
    android:id="@+id/textInputLayout"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:hint="Some Hint Text"
    android.support.design:hintAnimationEnabled="true"
    android.support.design:hintEnabled="true"
    android.support.design:layout_marginTop="16dp">

    <android.support.design.widget.TextInputEditText
        android:id="@+id/editText"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"/>

</android.support.design.widget.TextInputLayout>

我把这个作为回答发表在这里,因为我把书签弄混了。很抱歉我发了两次相同的回答。


这段代码在没有 android.support.design:hintAnimationEnabled 和 android.support.design:hintEnabled 的情况下能否正常工作?我查看了 TextInputLayout 源码,发现这两个属性在加载属性时都被设置为默认值。 - androidguy
@androidguy 是的,没有这些属性也应该可以工作。那些属性告诉TextInputLayout在布局中为这些项目分配空间(或者至少这就是我观察到的)。 - Azethoth
@Azethoth 这个解决方案无法保留原有的行为。在我的情况下,我是用它来实现浮动标签动画的。当我这样使用时,提示/标签不会出现。我只能看到一个文本输入框。 - KrishnaCA
@KrishnaCA 这很奇怪。我在我的应用程序中到处使用这种方法,它既在编辑文本中显示提示,又将其作为浮动标签进行动画处理。我不确定可能是什么原因导致了您的问题。您能否在问题中发布您的xml布局的代码示例并链接给我?我很乐意尝试协助。 - Azethoth
@KrishnaCA 我想知道这是否与华为为其Android版本所做的任何操作有关。您是否在模拟器或其他设备上进行了测试?您还可以通过在代码中设置编辑文本的提示来避免此崩溃。当提示在xml中设置时,该错误会显现出来。 - Azethoth
显示剩余2条评论

26
在您的EditText中添加以下属性:android:importantForAutofill="noExcludeDescendants"

如果您的最小API低于26,那么该功能仅适用于API 26,是否有解决方案? - JPM
2
@JPM 不用担心,它在旧的API级别中被忽略,所以不会崩溃或成为问题。 - Pei
2
@JPM问题只存在于Oreo版本中,因此对于旧的API将被忽略,并且不会导致它们崩溃。 - Gaurav Singh
我现在的应用程序中已经部署了,看起来运行得很好。 - JPM
@JPM 太棒了!! - Gaurav Singh
1
这是错误的解决方案。当您长按EditText并从菜单中选择Autofill时,它会崩溃。正确(尽管需要代码)的解决方案:https://dev59.com/2VcO5IYBdhLWcg3wgBlo#46698028 - PrzemekTom

12

Luke Simpson几乎做对了,只是应该使用"styles.xml"而不是"themes.xml"。

我创建了一个带有版本限定符的新样式文件,目标是v26,以使其更清晰。
只需复制并粘贴您的AppTheme到v26/styles.xml中,并将editTextStyle项添加到EditTextStyle样式中即可。

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    ...
    <item name="android:editTextStyle">@style/App_EditTextStyle</item>
    <item name="editTextStyle">@style/App_EditTextStyle</item>
</style>

<style name="App_EditTextStyle" parent="@android:style/Widget.EditText">
    <item name="android:importantForAutofill">noExcludeDescendants</item>
</style>

这样你就可以对所有 EditText 进行更改,而无需更改布局文件。


1
将会注明最低API要求,需要放置在v26资源文件夹中。 - StarWind0

6
你可以使用样式或在XML中设置任何importantForAutofill的值。这是修复当您聚焦于EditText时出现NPE的方法,但如果您长按EditText并单击AutoFill,则无法修复。我在此处找到了一个关于此错误的Bug报告,请添加星标并在Bug报告中分享您的观察结果。
谢谢。

6

我使用 v26/themes.xml 文件来覆盖 EditText 样式,只针对于 Android 8.0.0(Oreo)版本的自动填充功能:

<style name="EditTextStyle" parent="Widget.AppCompat.EditText">
    <item name="android:importantForAutofill">noExcludeDescendants</item>
</style>

请注意,我不得不为我的布局XML中的每个EditText应用内联样式,以使其生效。我曾尝试在我的应用程序主题中全局应用此更改,但出于某些原因它并没有起作用。
// HAD TO DO THIS IN LAYOUT XML FOR EACH EDIT TEXT
<EditText
    style="@style/EditTextStyle"
    ... />


// THIS DIDN'T TAKE EFFECT IN THEMES XML (HAS BEEN ADDED TO MANIFEST)
<style name="APP_THEME" parent="@style/Theme.AppCompat.Light">
    <item name="android:editTextStyle">@style/EditTextStyle</item>
    <item name="editTextStyle">@style/EditTextStyle</item>
</style>

1

@Luke Simpson是正确的。您可以在themes.XML中使用它,例如:

<item name="editTextStyle">@style/AppEditTextStyle</item>

and then put
<style name="AppEditTextStyle" parent="Widget.AppCompat.EditText">
        <item name="android:importantForAutofill">auto</item>
 </style>

在V26 / app_styles.xml中
但是,我还必须在默认文件夹的app_styles.xml中放置空标签。否则,EditText的所有属性都会被此覆盖,我的EditText无法正常工作。 当您为v26设置importantForAutoFill属性并且希望在8.1中使用自动填充时,只需简单地放置即可。
<style name="AppEditTextStyle" parent="Widget.AppCompat.EditText">
        <item name="android:importantForAutofill">auto</item>
    </style>

因此,自动填充属性在8.1中起作用。它将仅在8.0中禁用,因为崩溃发生在8.0中,并且已经在8.1中修复。

0

我也遇到了这个问题,最终我们找到了在Android 8.0和Android 8.1上崩溃的原因。

第一个原因(重要线索):XML中的空提示(android:hint="")会导致Oreo设备崩溃。请在整个项目搜索中删除此EditText中的空提示。

第二个原因(与上述解释相同):如果您使用了TextInputLayout,请确保您的EditText提示应显示在其中,否则您可以在EditText中使用提示。

希望这能帮到您!

谢谢


0
如果有人仍然想在“TextInputEditText”中使用“hint”,请在“TextInputLayout”中设置app:hintEnabled="false"
<com.google.android.material.textfield.TextInputLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:hintEnabled="false"
    app:passwordToggleEnabled="true">

    <com.google.android.material.textfield.TextInputEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="password"
        android:inputType="textPassword" />

</com.google.android.material.textfield.TextInputLayout>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接