在视图中定义样式和自定义属性而不是 xml
Define style and custom attribute in View instead of xml
我想为视图实现自定义样式。让我们以按钮为例。一些通用值将在应用程序中共享,因为我使用如下样式:
<style name="Widget.Demo.Button.Primary" parent="@style/Widget.MaterialComponents.Button">
<item name="fontFamily">@font/roboto</item>
<item name="android:fontFamily">@font/roboto</item>
<item name="android:minHeight">64dp</item>
<item name="android:theme">@style/ThemeOverlay.Demo.GrayPrimary</item>
</style>
<style name="ThemeOverlay.Demo.GrayPrimary" parent="">
<item name="colorPrimary">@color/gray</item>
</style>
现在我想在按钮中添加一些自定义属性,如下所示(这只是一个示例,不是真正的属性):
<com.android.CustomButton
android:id="@+id/btn_first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/first"
app:abc="primary"
style="@style/Widget.Demo.Button.Primary"/>
attrs.xml:
<declare-styleable name="CustomButtonAttr" >
<attr name="abc" format="enum" >
<enum name="primary" value="1"/>
<enum name="secondary" value="2"/>
</declare-styleable>
我不想每次都在 xml 中定义样式和自定义属性。有什么方法可以直接在我的自定义视图中获取自定义属性,并在我下面的 class?
中默认设置 Widget.Demo.Button.Primary
class CustomButton : MaterialButton {
constructor(context: Context) : super(context)
constructor(context: Context, attributeSet: AttributeSet) : super(
ThemeEnforcement.createThemedContext(context, attributeSet, 0, 0),
attributeSet,
0
)
}
我不想在 xml 中为我创建的每个按钮或视图定义样式。那么有没有办法在 CustomButton
class 中定义自定义属性?如果可以请给我一些参考。
提前致谢。
是的,您可以在构造函数中使用默认样式属性。
定义新属性:
<attr name="customButtonStyle" format="reference" />
然后使用合适的视图构造函数:
private val defStyleAttr = R.attr.customButtonStyle
class CustomButton(context: Context, attrs: AttributeSet) : MaterialButton(
ThemeEnforcement.createThemedContext(context, attributeSet, defStyleAttr, 0),
attributeSet,
defStyleAttr
) {
init {
val typedArray = context.obtainStyledAttributes(
attrs,
R.styleable.CustomButton,
defStyleAttr,
0
)
...
}
在您的主题中,将 customButtonStyle
指向您希望默认使用的样式资源:
<style name="Theme.Demo" parent="Base.Theme.Demo">
<item name="customButtonStyle">@style/Widget.Demo.Button.Primary</item>
</style>
请注意,该样式资源中的 android:theme
应更改为 materialThemeOverlay
,因为从默认样式读取时不会应用它。由于您已经使用 ThemeEnforcement
函数包装了上下文(较新版本的 Material Design Components 将其更改为 MaterialThemeOverlay
),此自定义视图支持 materialThemeOverlay
您也可以将自定义属性添加到样式中:
<style name="Widget.Demo.Button.Primary" parent="@style/Widget.MaterialComponents.Button">
<item name="abc">primary</item>
<item name="fontFamily">@font/roboto</item>
<item name="android:fontFamily">@font/roboto</item>
<item name="android:minHeight">64dp</item>
<item name="materialThemeOverlay">@style/ThemeOverlay.Demo.GrayPrimary</item>
</style>
我想为视图实现自定义样式。让我们以按钮为例。一些通用值将在应用程序中共享,因为我使用如下样式:
<style name="Widget.Demo.Button.Primary" parent="@style/Widget.MaterialComponents.Button">
<item name="fontFamily">@font/roboto</item>
<item name="android:fontFamily">@font/roboto</item>
<item name="android:minHeight">64dp</item>
<item name="android:theme">@style/ThemeOverlay.Demo.GrayPrimary</item>
</style>
<style name="ThemeOverlay.Demo.GrayPrimary" parent="">
<item name="colorPrimary">@color/gray</item>
</style>
现在我想在按钮中添加一些自定义属性,如下所示(这只是一个示例,不是真正的属性):
<com.android.CustomButton
android:id="@+id/btn_first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/first"
app:abc="primary"
style="@style/Widget.Demo.Button.Primary"/>
attrs.xml:
<declare-styleable name="CustomButtonAttr" >
<attr name="abc" format="enum" >
<enum name="primary" value="1"/>
<enum name="secondary" value="2"/>
</declare-styleable>
我不想每次都在 xml 中定义样式和自定义属性。有什么方法可以直接在我的自定义视图中获取自定义属性,并在我下面的 class?
中默认设置Widget.Demo.Button.Primary
class CustomButton : MaterialButton {
constructor(context: Context) : super(context)
constructor(context: Context, attributeSet: AttributeSet) : super(
ThemeEnforcement.createThemedContext(context, attributeSet, 0, 0),
attributeSet,
0
)
}
我不想在 xml 中为我创建的每个按钮或视图定义样式。那么有没有办法在 CustomButton
class 中定义自定义属性?如果可以请给我一些参考。
提前致谢。
是的,您可以在构造函数中使用默认样式属性。
定义新属性:
<attr name="customButtonStyle" format="reference" />
然后使用合适的视图构造函数:
private val defStyleAttr = R.attr.customButtonStyle
class CustomButton(context: Context, attrs: AttributeSet) : MaterialButton(
ThemeEnforcement.createThemedContext(context, attributeSet, defStyleAttr, 0),
attributeSet,
defStyleAttr
) {
init {
val typedArray = context.obtainStyledAttributes(
attrs,
R.styleable.CustomButton,
defStyleAttr,
0
)
...
}
在您的主题中,将 customButtonStyle
指向您希望默认使用的样式资源:
<style name="Theme.Demo" parent="Base.Theme.Demo">
<item name="customButtonStyle">@style/Widget.Demo.Button.Primary</item>
</style>
请注意,该样式资源中的 android:theme
应更改为 materialThemeOverlay
,因为从默认样式读取时不会应用它。由于您已经使用 ThemeEnforcement
函数包装了上下文(较新版本的 Material Design Components 将其更改为 MaterialThemeOverlay
),此自定义视图支持 materialThemeOverlay
您也可以将自定义属性添加到样式中:
<style name="Widget.Demo.Button.Primary" parent="@style/Widget.MaterialComponents.Button">
<item name="abc">primary</item>
<item name="fontFamily">@font/roboto</item>
<item name="android:fontFamily">@font/roboto</item>
<item name="android:minHeight">64dp</item>
<item name="materialThemeOverlay">@style/ThemeOverlay.Demo.GrayPrimary</item>
</style>