How to pass custom component parameters in java and xml

40,145

(Full disclosure: This question is an offshoot of Creating custom view)

You can create constructors beyond the three standard ones inherited from View that add the attributes you want...

MyComponent(Context context, String foo)
{
  super(context);
  // Do something with foo
}

...but I don't recommend it. It's better to follow the same convention as other components. This will make your component as flexible as possible and will prevent developers using your component from tearing their hair out because yours is inconsistent with everything else:

1. Provide getters and setters for each of the attributes:

public void setFoo(String new_foo) { ... }
public String getFoo() { ... }

2. Define the attributes in res/values/attrs.xml so they can be used in XML.

<?xml version="1.0" encoding="utf-8"?>
<resources>
  <declare-styleable name="MyComponent">
    <attr name="foo" format="string" />
  </declare-styleable>
</resources>

3. Provide the three standard constructors from View.

If you need to pick anything out of the attributes in one of the constructors that takes an AttributeSet, you can do...

TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.MyComponent);
CharSequence foo_cs = arr.getString(R.styleable.MyComponent_foo);
if (foo_cs != null) {
  // Do something with foo_cs.toString()
}
arr.recycle();  // Do this when done.

With all that done, you can instantiate MyCompnent programmatically...

MyComponent c = new MyComponent(context);
c.setFoo("Bar");

...or via XML:

<!-- res/layout/MyActivity.xml -->
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:blrfl="http://schemas.android.com/apk/res-auto"
  ...etc...
>
  <com.blrfl.MyComponent
   android:id="@+id/customid"
   android:layout_weight="1"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent"
   android:layout_gravity="center"
   blrfl:foo="bar"
   blrfl:quux="bletch"
  />
</LinearLayout>

Additional Resource - https://developer.android.com/training/custom-views/create-view

Share:
40,145
Emile
Author by

Emile

Creative developer for AKQA for the last 21+ years. Was primarily focused on flash development but have now moved on to explore other areas of interest. OpenCV, Cinder, Processing, Android, VR, AR.

Updated on July 09, 2022

Comments

  • Emile
    Emile almost 2 years

    When creating a custom component in android it is often asked how to create and pass through the attrs property to the constructor.

    It is often suggested that when creating a component in java that you simply use the default constructor, i.e.

    new MyComponent(context);
    

    rather than attempting to create an attrs object to pass through to the overloaded constructor often seen in xml based custom components. I've tried to create an attrs object and it doesn't seem either easy or at all possible (without an exceedingly complicated process), and by all accounts isn't really required.

    My question is then: What is the most efficient way of construction a custom component in java that passes or sets properties that would have otherwise been set by the attrs object when inflating a component using xml?

  • ahodder
    ahodder about 13 years
    I am aware this is way belated, but do you need to add xmlns:blrfl="schemas.android.com/apk/res/com.blrfl" to the manifest?
  • Andrew Simpson
    Andrew Simpson about 13 years
    Nope, just to the XML document where the namespace is used. I actually didn't notice that I'd cloned the Android namespace into the Blrfl namespace, which is wrong. That's been fixed.
  • espinchi
    espinchi almost 13 years
    Say you have defined MyComponent in XML, but the "foo" parameter is computed in the activity. Then you have to do ((MyComponent) findViewById(R.id.customid)).setFoo("computedFoo");. My question is: this needs to be done only after the setContentView call in the onCreate, right?
  • Emile
    Emile over 11 years
    Yes, the setContentView() is what would allow findViewById() to find the element in the view you'd requested to draw.
  • Serg Burlaka
    Serg Burlaka over 6 years
    Greate res-auto helps me
  • Phong Nguyen
    Phong Nguyen over 5 years
    thank a lot, every android dev should know this technique!
  • Phong Nguyen
    Phong Nguyen over 5 years
    @Blrfl just another thing, do you know how to add description/documentation for fields that declare in attrs.xml to clarify a field mission.
  • Andrew Simpson
    Andrew Simpson over 5 years
    @ThinkTwiceCodeOnce Sorry, I don't. It's been at least five years since I did any Android development.
  • SaPropper
    SaPropper over 2 years
    Thanks for your instructions! I just tried it and found out it didn't work as expected. Based on your explanations I thought that because you provide getters and setters the attributes set in XML are automatically set in code as well, which is NOT the case. I solved it by setting them in the constructor (as shown in 3.). The getters and setters (under 1.) are NOT needed.