androidinheritanceandroid-custom-viewdeclare-styleableandroid-attributes

Android: How to get an attribute from a super class of a custom view


I have a custom view A that has a TextView. I Made a method that returns the resourceID for the TextView. If no text is defined the method will return -1 by default. I also have a custom view B that inherits from view A. My custom view has the text 'hello'. When I call the method to get the attribute of the super class I get -1 back instead.

In the code there is also an example of how i'm able to retrieve the value but it feels kind of hacky.

attrs.xml

<declare-styleable name="A">
    <attr name="mainText" format="reference" />
</declare-styleable>

<declare-styleable name="B" parent="A">
    <attr name="subText" format="reference" />
</declare-styleable>

Class A

protected static final int UNDEFINED = -1;

protected void init(Context context, AttributeSet attrs, int defStyle)
{
     TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.A, defStyle, 0);

     int mainTextId = getMainTextId(a);

     a.recycle();

     if (mainTextId != UNDEFINED)
     {
        setMainText(mainTextId);
     }
}

protected int getMainTextId(TypedArray a)
{
  return a.getResourceId(R.styleable.A_mainText, UNDEFINED);
}

Class B

protected void init(Context context, AttributeSet attrs, int defStyle)
{
  super.init(context, attrs, defStyle);

  TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.B, defStyle, 0);

  int mainTextId = getMainTextId(a); // this returns -1 (UNDEFINED)

  //this will return the value but feels kind of hacky
  //TypedArray b = context.obtainStyledAttributes(attrs, R.styleable.A, defStyle, 0);
  //int mainTextId = getMainTextId(b); 

  int subTextId = getSubTextId(a);

  a.recycle();

  if (subTextId != UNDEFINED)
  {
     setSubText(subTextId);
  }
}

Another solution I have found so far is to do the following. I also think this is kind of hacky.

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

<declare-styleable name="A">
    <attr name="mainText" />
</declare-styleable>

<declare-styleable name="B" parent="A">
    <attr name="mainText" />
    <attr name="subText" format="reference" />
</declare-styleable>

How to get an attribute from a super class of a custom view? I can't seem to find any good examples on how inheritance works with custom views.


Solution

  • Apparently this is the right way to do it:

    protected void init(Context context, AttributeSet attrs, int defStyle) {
        super.init(context, attrs, defStyle);
    
        TypedArray b = context.obtainStyledAttributes(attrs, R.styleable.B, defStyle, 0);
        int subTextId = getSubTextId(b);
        b.recycle();
    
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.A, defStyle, 0);
        int mainTextId = getMainTextId(a);
        a.recycle();
    
        if (subTextId != UNDEFINED) {
            setSubText(subTextId);
        }
    }
    

    There is an example at the source of TextView.java. at line 1098