What's the point of declare-styleable? - android

Suppose I am making some new views with styleable attributes. I declare them thusly (this is how the documentation says to do it:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TriangleView">
<attr name="direction">
<enum name="NE" value="0" />
<enum name="NW" value="1" />
<enum name="SW" value="2" />
<enum name="SE" value="3" />
</attr>
</declare-styleable>
<declare-styleable name="BannerView">
<attr name="direction">
<enum name="NE" value="0" />
<enum name="NW" value="1" />
<enum name="SW" value="2" />
<enum name="SE" value="3" />
</attr>
<attr name="thickness" format="dimension" />
</declare-styleable>
</resources>
However, this won't work because all attributes are apparently in the same namespace, and I get the error Error: Attribute "direction" has already been defined.
So apparently I have to move the apparently duplicated attributes outside the <declare-styleable> like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="direction">
<enum name="NE" value="0" />
<enum name="NW" value="1" />
<enum name="SW" value="2" />
<enum name="SE" value="3" />
</attr>
<declare-styleable name="BannerView">
<attr name="thickness" format="dimension" />
</declare-styleable>
</resources>
But this poses two questions:
If this works, what exactly is the point of <declare-styleable>?
What if I want the attribute to behave differently in different views? For example if BannerView's direction can only be up or down.

What exactly is the point of <declare-styleable>?
<declare-stylable> tags let you declare attributes for your custom views that you can then set for those views in xml. There are really 3 parts to using the attribute:
Declare an <attr> inside of a <declare-stylable> tag.
Define a custom namespace in your xml layout pointing to your app package name (ex. app). Use the custom attribute in your layout (ex. app:direction="NW").
In your custom view, override the constructors with an AttributeSet parameter, get a TypedArray and read the custom attributes, if any, from it and then within the constructor tell the view how to use those attributes appropriately.
What if I want the attribute to behave differently in different views?
For example if BannerView's direction can only be up or down.
Try something like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="direction">
<enum name="NE" value="0" />
<enum name="NW" value="1" />
<enum name="SW" value="2" />
<enum name="SE" value="3" />
</attr>
<declare-styleable name="TriangleView">
<attr name="direction" />
</declare-styleable>
<declare-styleable name="BannerView">
<attr name="direction" />
<attr name="thickness" format="dimension" />
</declare-styleable>
</resources>
When you build your xml layout for TriangleView or BannerView, you can use the app:direction="NW" example for both. In the constructors with AttributeSet in TriangleView or BannerView, the attributes will have the same format as the original, but what you do with that value is dependent on your implementation of the constructors in each respective view (can be the same or different for both).
If you want attributes to be defined differenly (ie. different "format" or "enum") for different views, then you have to create different attributes with different names.

Related

Custom View. attrs array

I have a custom view with 4 rectangles in it. I want to make this view configurable from xml.
Is it possible to make it like:
custom:rectColor="red|cyan|blue|green" //each color correspond rectangle
with
<attr name="rectColor" format="color">
<flag name="red" value="2" />
<flag name="cyan" value="5" />
<flag name="blue" value="7" />
<flag name="green" value="9" />
</attr>
Or it must be:
<attr name="firstRectColor" format="color" />
<attr name="secondRectColor" format="color" />
<attr name="thirdRectColor" format="color" />
<attr name="fourthRectColor" format="color" />
and each view should contains:
custom:firstRectColor="red"
custom:secondRectColor="red"
custom:thirdRectColor="red"
custom:fourthRectColor="red"
And if it possible. How can I get set of color values from attributes.
Thanks
Read this documentation.. it shows you how to declare custom attributes and access them in your layout file..
http://developer.android.com/training/custom-views/create-view.html

In android, is it possible to use enumerated resource ids in code?

I would like to declare some values in resources like this:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="Shape">
<attr name="type" format="enum">
<enum name="rect" value="0"/>
<enum name="circle" value="1"/>
<enum name="square" value="2"/>
</attr>
</declare-styleable>
Use them like this in the layout:
<view
class="org.frame_lang.saveandloadhierarchydemo.view.SelectShapeScreenView$Shape"
android:id="#+id/rectangleBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
framelang:shapeType="rect"
/>
And then be able to reference the actual enum ids in code using the xml decl somehow. You can reference the attribute by:
R.styleable.Shape_shapeType
But don't seem to be able to do something like this for the actual values:
R.styleable.Shape_shapeType.rect
R.styleable.Shape_shapeType.circle
R.styleable.Shape_shapeType.triangle
Thanks!

Using Enums as Custom XML Attributes

I want to use custom components in my project and i want to add it to enum attributes like below , how can i do that ?
<com.abb.abbcustomcompanents.buttons.AbbButton
android:id="#+id/abbBtn1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:Type="How can i use enum here"
/>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="abbButton">
<attr name="Type" format="enum"/>
<attr name="onAction" format="string"/>
</declare-styleable>
</resources>
Thank you !
Ex :
<attr name="myProperty" format="enum">
<enum name="None" value="0"/>
<enum name="One" value="1"/>
<enum name="Two" value="2"/>
<enum name="Three" value="3"/>
</attr>
Use like this:
<YourCustomView
...
app:myProperty="One"/>
Reference
https://stackoverflow.com/a/15231645/1329126
Order inside the XML matters, at least to eclipse. Define your enum above (or inside) your declare-styleable... not below.
<attr name="quality">
<enum name="Good" value="1" />
<enum name="Better" value="2" />
<enum name="Best" value="3" />
</attr>
<declare-styleable name="SquareView">
<attr name="quality" />
</declare-styleable>
<declare-styleable name="CircleView">
<attr name="quality" />
</declare-styleable>
I had a very long enum so I placed it at the end of my XML to improve readability. It would parse correctly but reject values in Design mode.

Getting Android enum descriptions to appear in JavaDoc

I have defined a custom attribute in xml that must take an enum value as a parameter. The JavaDoc that is automatically produced from my application's R.attr builds a table with enum name and value, but filling in the description column eludes me. How do I define a description that will appear in the JavaDoc?
An example attribute with enum constants:
<declare-styleable name="MyCustomView">
<attr name="directions">
<enum name="up" value="0" />
<enum name="down" value="1" />
<enum name="left" value="2" />
<enum name="right" value="3" />
</attr>
</declare-styleable>
To show what I mean, the JavaDoc for directionPriority in android.R.attr has a table for all the possible enums with "constant," "value" and "description" all filled in.
I have done a good deal of research and tried trial-and-error guesses at a tag that might allow me to include a description, but to no avail. Does anyone know the proper way to document this?
The solution is to add comments before each of the enums. These comments are automatically translated into the enum description column.
<declare-styleable name="MyCustomView">
<attr name="directions">
<!-- Go up! -->
<enum name="up" value="0" />
<!-- Go down! -->
<enum name="down" value="1" />
<!-- Go left! -->
<enum name="left" value="2" />
<!-- Go right! -->
<enum name="right" value="3" />
</attr>
</declare-styleable>

Format attribute value "android:drawable" not valid

I'm trying to create custom attributes to my button but I dont know which format I must use to images in attributes declaration...
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TCButton">
<attr name="Text" format="string"/>
<attr name="BackgroundImage" format="android:drawable" />
</declare-styleable>
</resources>
Error is in the format="android:drawable"...
You can use format="integer", the resource id of the drawable, and AttributeSet.getDrawable(...).
Here is an example.
Declare the attribute as integer in res/values/attrs.xml:
<resources>
<declare-styleable name="MyLayout">
<attr name="icon" format="integer" />
</declare-styleable>
</resources>
Set the attribute to a drawable id in your layout:
<se.jog.MyLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
myapp:icon="#drawable/myImage"
/>
Get the drawable from the attribute in your custom widget component class:
ImageView myIcon;
//...
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyLayout);
Drawable drawable = a.getDrawable(R.styleable.MyLayout_icon);
if (drawable != null)
myIcon.setBackgroundDrawable(drawable);
To see all options possible check the android src here
I think it will be better to use it as a simple reference:
<declare-styleable name="TCButton">
<attr name="customText" format="string"/>
<attr name="backgroundImage" format="reference" />
</declare-styleable>
And set it in your xml like this:
<your.package.name.TCButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
custom:customText="Some custom text"
custom:backgroundImage="#drawable/myImage"
/>
And in your class set the attributes like this:
public TCButton(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.MembershipItemView, 0, 0);
String customText;
Drawable backgroundImage;
try {
customText = a.getString(R.styleable.TCButton_customText);
backgroundImage = a.getDrawable(R.styleable.TCButton_backgroundImage);
} finally {
a.recycle();
}
if(!TextUtils.isEmpty(customText)) {
((TextView)findViewById(R.id.yourTextView)).setText(customText);
}
if(null != backgroundImage) {
((ImageView)findViewById(R.id.yourImageView)).setBackgroundDrawable(backgroundImage);
}
}
PS:
Don't forget to add this line for the root element of the layout you are using your custom view in
xmlns:custom="http://schemas.android.com/apk/res-auto"
If you don't set this, you won't be able to access your custom attributes.
From AOSP code, I found how google engineers declare ImageView#src attr.
<declare-styleable name="ImageView">
<attr name="src" format="reference|color" />
<attr name="scaleType">
<enum name="matrix" value="0" />
<enum name="fitXY" value="1" />
<enum name="fitStart" value="2" />
<enum name="fitCenter" value="3" />
<enum name="fitEnd" value="4" />
<enum name="center" value="5" />
<enum name="centerCrop" value="6" />
<enum name="centerInside" value="7" />
</attr>
<attr name="adjustViewBounds" format="boolean" />
<attr name="maxWidth" format="dimension" />
<attr name="maxHeight" format="dimension" />
<attr name="tint" format="color" />
<attr name="baselineAlignBottom" format="boolean" />
<attr name="cropToPadding" format="boolean" />
<attr name="baseline" format="dimension" />
<attr name="drawableAlpha" format="integer" />
<attr name="tintMode" />
</declare-styleable>
Above code is a sample and it can cover most case in our development.

Categories

Resources