EditText 的子项 class 看起来与 Android 上的普通 EditText 不同 4

Child class of EditText looks different than normal EditText on Android 4

这是我在开发真实应用程序时发现的 'bug',但我创建了一个空白项目来重现它。

我有以下布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:id="@+id/root"
    android:orientation="vertical"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

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

    <com.example.test.testapp.MyEditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />


</LinearLayout>

class MyEditText 看起来像这样:

public class MyEditText extends EditText {

    public MyEditText(Context context){
        super(context);
    }

    public MyEditText(Context context, AttributeSet attrs){
        super(context, attrs);
    }


    public MyEditText(Context context, AttributeSet attrs, int defStyle){
        super(context, attrs, defStyle);
    }


}

我的styles.xml文件除了主题

是空的
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
    </style>

</resources>

我希望 MyEditText 看起来像正常的 EditText 并且它在 Android 5.0 上确实如此,但在 Android 2.3.7 上不是,Android 4.1.3 或 Android 4.4.4。

在那些 Android 版本中,EditText 的颜色不同,正常版本在聚焦时有青色下划线,自定义版本有黑色下划线:

为什么会发生这种情况,我该如何预防?

编辑/更新:

Google seems to have adressed this 在支持库中引入了一个 AppCompatEditText class。

Why is this happening

因为您正在使用 AppCompat。引用 the blog post on the subject:

Q: Why is my EditText (or other widget listed above) not being tinted correctly on my pre-Lollipop device?

A: The widget tinting in AppCompat works by intercepting any layout inflation and inserting a special tint-aware version of the widget in its place. For most people this will work fine, but I can think of a few scenarios where this won’t work, including:

  • You have your own custom version of the widget (i.e. you’ve extended EditText)
  • You are creating the EditText without a LayoutInflater (i.e., calling new EditText()).

因此,该行为是预期的。 AppCompat 向后移植提供了一些轻量级的着色向后移植,但它不会处理所有情况。

how can I prevent it?

即兴表演,或者:

  • 不要创建 EditText

  • 的子类
  • 当 运行 在 AppCompat 上时,查看色调并找出如何自己应用它,也许通过检查 AppCompat 源代码(假设它可用 - 我没看过为它),或

  • 不要使用 AppCompat,并在 Android 5.0+ 设备上使用 Theme.Material 查看着色是否按预期工作

未来的 AppCompat 可能会为子类提供某种系统以参与着色过程。可能还有其他解决方案 -- 这些是我想到的。

实际上,在此处接受的答案中得出的结论并不完全正确(不再)。您应该 使用 AppCompat,但只需要意识到 AppCompat 会在布局期间用 AppCompatEditText 替换您的 EditText inflation。同样的过程也发生在其他一些 UI 元素上,例如 Switch、CheckBoxes 等。Google 这样做是为了让他们可以将 Material 设计的外观和感觉推得更远更广用户的代码更改最少。

如果你想继承 EditText,你应该继承 AppCompatEditText (android.support.v7.widget.AppCompatEditText)。