以编程方式设置 TextInputLayout 主题
Set TextInputLayout theme programmatically
有没有办法在 Android 中以编程方式更改 TextInputLayout 的主题。
如果我有以下 TextInputLayout for ex.:
<android.support.design.widget.TextInputLayout
android:id="@+id/label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:paddingTop="16dp"
android:theme="@style/TextInputLayoutTheme"
app:errorTextAppearance="@style/Error">
<android.support.v7.widget.AppCompatEditText
android:id="@+id/edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dp"
android:paddingTop="8dp"/>
</android.support.design.widget.TextInputLayout>
我能否以某种方式将这一行 android:theme="@style/TextInputLayoutTheme"
以编程方式更改为另一个主题?
没有 方法可以在运行时 更改任何视图或任何布局的主题。因为主题和样式是在视图创建期间递归应用的。 (主题也适用于布局的子视图)
但是,您可以在创建视图之前使用 XML 布局或以编程方式更改该主题。
以编程方式:
方法 1 - 通过用 android.view.ContextThemeWrapper
包装 Context
以编程方式创建 TextInputLayout
并使用。
TextInputLayout layout = new TextInputLayout(new ContextThemeWrapper(getContext(), R.style. TextInputLayoutTheme));
方法 2 - 扩展 TextInputLayout 并使用您自己的布局。将 ContextThemeWrapper
作为上下文传递。
public class MyTextInputLayout extends TextInputLayout {
public MyTextInputLayout(Context context) {
super(new ContextThemeWrapper(context, R.style.AppTheme));
}
public MyTextInputLayout(Context context, AttributeSet attrs) {
super(new ContextThemeWrapper(context, R.style.AppTheme), attrs);
}
public MyTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(new ContextThemeWrapper(context, R.style.AppTheme), attrs, defStyleAttr);
}
}
现在,您可以在 XML 布局中使用 MyTextInputLayout
XML布局:
1) 在 attrs.xml
文件中,创建名为 textInputLayoutTheme
的新属性
<attr name="textInputLayoutTheme" format="reference"/>
2) 在 styles.xml
文件中的 AppTheme
中,将 @style/TextInputLayoutTheme
设置为 textInputLayoutTheme
.
<resources>
<style name="AppTheme" parent="PARENT_THEME">
<item name="textInputLayoutTheme">@style/TextInputLayoutTheme</item>
</style>
<style name="AppTheme.Secondary">
<item name="textInputLayoutTheme">@style/TextInputLayoutTheme_Secondary</item>
</style>
</resources>
3) 在您的 layout.xml
文件中,将 ?attr/textInputLayoutTheme
设置为 TextInputLayout
主题
<android.support.design.widget.TextInputLayout
android:id="@+id/label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:paddingTop="16dp"
android:theme="@?attr/textInputLayoutTheme"
app:errorTextAppearance="@style/Error">
现在,当您将应用程序主题从 AppTheme
更改为 AppTheme.Secondary
时,TextInputLayoutTheme_Secondary
将用作 TextInputLayout
的主题,而不是 TextInputLayoutTheme
.
不幸的是,接受的答案对我不起作用。
我的解决方案是将 TextInputLayout
包装在自定义布局中。
view_input_layout_wrapper.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:theme="@style/AppThemeMaterial"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
</FrameLayout>
TextInputLayoutWrapper
class TextInputLayoutWrapper(context: Context) : FrameLayout(context) {
var inputLayout: TextInputLayout
private set
init {
inflate(context, R.layout.view_input_layout_wrapper, this)
inputLayout = findViewById(R.id.til)
}
}
视图中的实现(fragment/activity):
private fun addNewField(fieldName: String) {
val textInputLayoutWrapper = TextInputLayoutWrapper(
requireContext()
).apply {
inputLayout.hint = fieldName
}
fieldsContainerViewGroup.addView(textInputLayoutWrapper)
}
注意:我的应用主题不是material主题,所以我必须在[=]的根ViewGroup
中添加theme="@style/AppThemeMaterial"
14=].
<style name="AppThemeMaterial" parent="Theme.MaterialComponents.Light">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:windowBackground">@android:color/black</item>
</style>
有没有办法在 Android 中以编程方式更改 TextInputLayout 的主题。 如果我有以下 TextInputLayout for ex.:
<android.support.design.widget.TextInputLayout
android:id="@+id/label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:paddingTop="16dp"
android:theme="@style/TextInputLayoutTheme"
app:errorTextAppearance="@style/Error">
<android.support.v7.widget.AppCompatEditText
android:id="@+id/edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="8dp"
android:paddingTop="8dp"/>
</android.support.design.widget.TextInputLayout>
我能否以某种方式将这一行 android:theme="@style/TextInputLayoutTheme"
以编程方式更改为另一个主题?
没有 方法可以在运行时 更改任何视图或任何布局的主题。因为主题和样式是在视图创建期间递归应用的。 (主题也适用于布局的子视图)
但是,您可以在创建视图之前使用 XML 布局或以编程方式更改该主题。
以编程方式:
方法 1 - 通过用 android.view.ContextThemeWrapper
包装 Context
以编程方式创建 TextInputLayout
并使用。
TextInputLayout layout = new TextInputLayout(new ContextThemeWrapper(getContext(), R.style. TextInputLayoutTheme));
方法 2 - 扩展 TextInputLayout 并使用您自己的布局。将 ContextThemeWrapper
作为上下文传递。
public class MyTextInputLayout extends TextInputLayout {
public MyTextInputLayout(Context context) {
super(new ContextThemeWrapper(context, R.style.AppTheme));
}
public MyTextInputLayout(Context context, AttributeSet attrs) {
super(new ContextThemeWrapper(context, R.style.AppTheme), attrs);
}
public MyTextInputLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(new ContextThemeWrapper(context, R.style.AppTheme), attrs, defStyleAttr);
}
}
现在,您可以在 XML 布局中使用 MyTextInputLayout
XML布局:
1) 在 attrs.xml
文件中,创建名为 textInputLayoutTheme
<attr name="textInputLayoutTheme" format="reference"/>
2) 在 styles.xml
文件中的 AppTheme
中,将 @style/TextInputLayoutTheme
设置为 textInputLayoutTheme
.
<resources>
<style name="AppTheme" parent="PARENT_THEME">
<item name="textInputLayoutTheme">@style/TextInputLayoutTheme</item>
</style>
<style name="AppTheme.Secondary">
<item name="textInputLayoutTheme">@style/TextInputLayoutTheme_Secondary</item>
</style>
</resources>
3) 在您的 layout.xml
文件中,将 ?attr/textInputLayoutTheme
设置为 TextInputLayout
主题
<android.support.design.widget.TextInputLayout
android:id="@+id/label"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:paddingTop="16dp"
android:theme="@?attr/textInputLayoutTheme"
app:errorTextAppearance="@style/Error">
现在,当您将应用程序主题从 AppTheme
更改为 AppTheme.Secondary
时,TextInputLayoutTheme_Secondary
将用作 TextInputLayout
的主题,而不是 TextInputLayoutTheme
.
不幸的是,接受的答案对我不起作用。
我的解决方案是将 TextInputLayout
包装在自定义布局中。
view_input_layout_wrapper.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:theme="@style/AppThemeMaterial"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/til"
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/edit_text"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
</FrameLayout>
TextInputLayoutWrapper
class TextInputLayoutWrapper(context: Context) : FrameLayout(context) {
var inputLayout: TextInputLayout
private set
init {
inflate(context, R.layout.view_input_layout_wrapper, this)
inputLayout = findViewById(R.id.til)
}
}
视图中的实现(fragment/activity):
private fun addNewField(fieldName: String) {
val textInputLayoutWrapper = TextInputLayoutWrapper(
requireContext()
).apply {
inputLayout.hint = fieldName
}
fieldsContainerViewGroup.addView(textInputLayoutWrapper)
}
注意:我的应用主题不是material主题,所以我必须在[=]的根ViewGroup
中添加theme="@style/AppThemeMaterial"
14=].
<style name="AppThemeMaterial" parent="Theme.MaterialComponents.Light">
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="android:windowBackground">@android:color/black</item>
</style>