从父级样式定义中获取子元素的样式属性

9

这个问题的标题可能有点无意义。我正在创建一些自定义视图,它们将被放置在一个单独的父布局中 - 一个自定义的FrameLayout

这些自定义视图有它们自己的样式属性,这些属性使用父布局的样式属性进行设置。

Parent为例,它是自定义的FrameLayout。它的样式attrattrs.xml中定义:

<attr name="parentStyleAttr" format="reference" />

Child也有它自己的属性:

<attr name="childStyleAttr" format="reference" />

Parent 则定义了它的可定义样式属性为:

<declare-styleable name="Parent">
    <attr name="childStyleAttr" />
</declare-styleable>

Child's 可定义的属性:

<declare-styleable name="Child">
    <attr name="childBgColor" format="color" />
</declare-styleable>

接下来,我为父元素定义一个样式:
<style name="ParentStyle">
    <item name="childStyleAttr">@style/ChildStyle</item>
</style>

还有一个用于 Child 的:

<style name="ChildStyle">
    <item name="childBgColor">@color/blah</item>
</style>

对于Parent,我在应用程序的主题中设置了parentStyleAttr

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="parentStyleAttr">@style/ParentStyle</item>
</style>

现在,当创建Parent时,它会填充包含Child的布局:
LayoutInflater.from(getContext()).inflate(R.layout.child, this, true);

在初始化Child时,我需要读取@style/ChildStyle中设置的样式属性值-childBgColor

以下方法不可行:

final TypedArray a = context.obtainStyledAttributes(attrs,
          R.styleable.Child, R.attr.childStyleAttr, R.style.ChildStyle);

我目前读取 attr/childBgColor 的方式是:

public Child(Context context, AttributeSet attrs, int defStyleAttr) {
    super(createThemeWrapper(context), attrs, defStyleAttr);
    initialize(attrs, defStyleAttr, R.style.ChildStyle);
}

private static ContextThemeWrapper createThemeWrapper(Context context) {
    final TypedArray forParent = context.obtainStyledAttributes(
            new int[]{ R.attr.parentStyleAttr });
    int parentStyle = forParent.getResourceId(0, R.style.ParentStyle);
    forParent.recycle();

    TypedArray forChild = context.obtainStyledAttributes(parentStyle,
            new int[]{ R.attr.childStyleAttr });
    int childStyleId = forChild.getResourceId(0, R.style.ChildStyle);
    forChild.recycle();

    return new ContextThemeWrapper(context, childStyleId);
}

void initialize(AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    Context context = getContext();
    final Resources res = getResources();

    final TypedArray a = context.obtainStyledAttributes(R.styleable.Child);

    ....
}

我不确定这是否是正确的方法。有人能帮助澄清一下吗?


你的代码出了问题或者想要改进它吗? - Nik Myers
@NikMyers 我想知道我目前的方法是否正确。如果不正确,正确的方法是什么? - Vikram
1
我可能理解有误,但你所描述的问题听起来像是最近appcompat更新中实现的父主题继承:https://chris.banes.me/2015/04/22/support-libraries-v22-1-0/#androidtheme 作者提到了LayoutInflater.Factory2作为启用父主题继承的类。 - hidro
读取子项中的XML属性并创建getter方法不是更简单吗? - Bojan Kseneman
@BojanKseneman 很抱歉,我不明白。 在子元素中读取xml属性是否更简单... 这就是我想做的。为了使事情更清晰,我可以在 AppTheme 下初始化 childStyleAttr 并很好地读取 childBgColor。但如果我选择这样做,我将不得不为 AppTheme 下的 所有 子项初始化样式属性。相反,我希望设置 parentStyleAttr,它应该处理所有子项的样式属性。 - Vikram
1个回答

1

我会选择简单的解决方案,即扩展布局并创建自定义布局,将其属性发送给其子项同时添加它们


你已经链接到了addViewInLayout(View child, int index, LayoutParams params, boolean preventRequestLayout)。我该如何使用它来读取Child的样式属性? - Vikram
通过覆盖此方法,您将能够访问已添加的每个子项,以便您可以以编程方式插入所需的属性。 - Muhannad Fakhouri
抱歉,我不在寻找替代方案。根据Android指南,样式信息应该使用属性进行设置。否则,样式、属性等就没有任何意义,因为所有的操作都可以在Java端完成。 - Vikram

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