114

I know it is possible to create custom UI element (by way of View or specific UI element extension). But is it possible to define new properties or attributes to newly created UI elements (I mean not inherited, but brand new to define some specific behavior I am not able to handle with default propertis or attributes)

e.g. element my custom element:

<com.tryout.myCustomElement
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="Element..."
   android:myCustomValue=<someValue>
/>

So is it possible to define MyCustomValue?

Thx

Waypoint
  • 15,705
  • 36
  • 110
  • 167
  • 3
    http://stackoverflow.com/questions/2695646/declaring-a-custom-android-ui-element-using-xml – Selvin Sep 30 '11 at 09:56
  • Hey here you have some nice article about the custom attributes in android - https://amcmobileware.org/android/blog/2016/09/11/custom-attributes/ – Arkadiusz Cieśliński Nov 15 '16 at 19:46
  • Have a look at my answer on [this](https://stackoverflow.com/questions/3441396/defining-custom-attrs/25648349#25648349) related question. – Helios Nov 20 '17 at 12:34

3 Answers3

258

Yes. Short guide:

1. Create an attribute XML

Create a new XML file inside /res/values/attrs.xml, with the attribute and it's type

<?xml version="1.0" encoding="UTF-8"?>
<resources>
    <declare-styleable name="MyCustomElement">
        <attr name="distanceExample" format="dimension"/>
    </declare-styleable>
</resources>

Basically you have to set up one <declare-styleable /> for your view that contains all your custom attributes (here just one). I never found a full list of possible types, so you need to look at the source for one I guess. Types that I know are reference (to another resource), color, boolean, dimension, float, integer and string. They are pretty self-explanatory

2. Use the attributes in your layout

That works the same way you did above, with one exception. Your custom attribute needs it's own XML namespace.

<com.example.yourpackage.MyCustomElement
   xmlns:customNS="http://schemas.android.com/apk/res/com.example.yourpackage"
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:text="Element..."
   customNS:distanceExample="12dp"
   />

Pretty straight forward.

3. Make use of the values you get passed

Modify the constructor of your custom view to parse the values.

public MyCustomElement(Context context, AttributeSet attrs) {
    super(context, attrs);

    TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.MyCustomElement, 0, 0);
    try {
        distanceExample = ta.getDimension(R.styleable.MyCustomElement_distanceExample, 100.0f);
    } finally {
        ta.recycle();
    }
    // ...
}

distanceExample is a private member variable in this example. TypedArray got lot's of other things to parse other types of values.

And that's it. Use the parsed value in your View to modify it, e.g. use it in onDraw() to change the look accordingly.

uthark
  • 5,173
  • 2
  • 41
  • 57
  • 7
    Just note about TypedArray. Be sure to call recycle() when done with them. – zskalnik Jan 17 '13 at 14:54
  • Here you can find a good list https://github.com/android/platform_frameworks_base/blob/master/core/res/res/values/attrs.xml – yahya Mar 04 '13 at 12:23
  • Does the IDE (eclipse for example) auto-complete the keys/values of custom attributes? – AlikElzin-kilaka Feb 11 '14 at 07:13
  • @kilaka I know that android studio does, it auto-completes custom enum types and knows that you're using @string/ and @dimen/ resource names and auto-completes them also. – Evan Leis Feb 26 '14 at 23:31
  • 23
    for gradle builds you should use `http://schemas.android.com/apk/res-auto` when declaring the custom namespace – Dori May 20 '14 at 11:07
  • Create a new XML file inside /res/values/attrs.xml.... how to insert a file into a file? – jerinho.com May 05 '15 at 03:43
  • @Dagon I think he meant create declare-styleable tag if the attrs.xml exists. If not, create a new xml file – Kelok Chan Jun 03 '16 at 05:41
  • I got a message: `In Gradle Project, always use https://schema.android.com/apk/res-auto for custom attributes` – K.Sopheak May 24 '17 at 09:08
  • 3
    In step 3, you can simply use `String initialText = attrs.getAttributeValue("http://schemas.android.com/apk/res-auto", "initialText");` where attr is the AttributeSet that is passed in the constructor and 'initialText' is your custom attribute name – kosiara - Bartosz Kosarzycki Dec 14 '17 at 08:13
  • [https://chaosinmotion.blog/2009/01/19/valid-format-values-for-declare-styleableattr-tags/https://chaosinmotion.blog/2009/01/19/valid-format-values-for-declare-styleableattr-tags/https://chaosinmotion.blog/2009/01/19/valid-format-values-for-declare-styleableattr-tags/https://chaosinmotion.blog/2009/01/19/valid-format-values-for-declare-styleableattr-tags/https://chaosinmotion.blog/2009/01/19/valid-format-values-for-declare-styleableattr-tags/] A full list of Atts types. I thought of posting for you, as you said you never found a full list. – Jai Pandit Mar 20 '18 at 23:44
21

In your res/values folder create attr.xml. There you can define your attribues:

<declare-styleable name="">
    <attr name="myCustomValue" format="integer/boolean/whatever" />
</declare-styleable>

When you then want to use it in your layout file you have to add

xmlns:customname="http://schemas.android.com/apk/res/your.package.name"

and then you can use the value with customname:myCustomValue=""

Maria Neumayer
  • 3,299
  • 3
  • 25
  • 43
-11

Yes , you can.Just use <resource> tag.
like this:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <style name="CodeFont" parent="@android:style/TextAppearance.Medium">
        <item name="android:layout_width">fill_parent</item>
        <item name="android:layout_height">wrap_content</item>
        <item name="android:textColor">#00FF00</item>
        <item name="android:typeface">monospace</item>
    </style>
</resources>

link from official website

Frank Cheng
  • 5,429
  • 8
  • 45
  • 71
  • Thanks for answer. But in resource, i see using default "android:" values. My point is, can I have e.g. android:phoneNameSelected="true" as a parameter of my custom UI element? – Waypoint Sep 30 '11 at 09:48