Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Obtain styled attributes for child from parent's style definition

Tags:

android

attr

xml

The question title is probably nonsensical. I am creating a bunch of custom views that will be placed in a single parent layout - a custom FrameLayout.

These custom views have their own style attr which are set using the parent's style attr.

As an example, consider Parent to be the custom FrameLayout. Its style attr is defined in attrs.xml:

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

The Child also has its attr:

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

And Parent defines its styleable attr as:

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

Child's styleable attr:

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

Following this, I define a style for the parent:

<style name="ParentStyle">
    <item name="childStyleAttr">@style/ChildStyle</item>
</style>

and one for Child:

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

For Parent, I set up parentStyleAttr in the app's theme:

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

Now, when Parent is created, it inflates a layout containing Child:

LayoutInflater.from(getContext()).inflate(R.layout.child, this, true);

During Child's initialization, I need to read the value of the style attribute set in @style/ChildStyle - childBgColor.

This doesn't work:

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

The way I am currently reading attr/childBgColor is:

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);

    ....
}

I am not confident if this is the right approach. Can someone help shed some some light on this?

like image 452
Vikram Avatar asked May 09 '15 19:05

Vikram


1 Answers

I would go for the simple solution which extending the Layout and create a custom layout that sends it attributes to it's children while adding them

like image 93
Muhannad Fakhouri Avatar answered Nov 15 '22 04:11

Muhannad Fakhouri