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.
Related
I've written a number picker that supports Integer and Float - therefore I've written a generic base class and define two derived typed class like NumberPickerInt and NumberPickerFloat. Those custom views do share a set of common xml settings but also a set of settings, that should be named the same but have different types, like following example shows:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="mnp_prefix" format="string|reference" />
<attr name="mnp_suffix" format="string|reference" />
<attr name="mnp_editTextStyle" format="reference" />
<attr name="mnp_buttonWidth" format="dimension" />
<attr name="mnp_iconUp" format="reference" />
<attr name="mnp_iconDown" format="reference" />
<attr name="mnp_iconUpLarge" format="reference" />
<attr name="mnp_iconDownLarge" format="reference" />
<attr name="mnp_longPressRepeatClicks" format="boolean" />
<attr name="mnp_style" format="enum">
<enum name="input" value="0" />
<enum name="scroll" value="1" />
</attr>
<declare-styleable name="MaterialNumberPickerInteger">
<attr name="mnp_valueInt" format="integer" />
<attr name="mnp_stepSizeInt" format="integer" />
<attr name="mnp_stepSizeLargeInt" format="integer" />
<attr name="mnp_minInt" format="integer" />
<attr name="mnp_maxInt" format="integer" />
<attr name="mnp_prefix" />
<attr name="mnp_suffix" />
<attr name="mnp_editTextStyle" />
<attr name="mnp_buttonWidth" />
<attr name="mnp_iconUp" />
<attr name="mnp_iconDown" />
<attr name="mnp_iconUpLarge" />
<attr name="mnp_iconDownLarge" />
<attr name="mnp_longPressRepeatClicks" />
<attr name="mnp_orientation" />
<attr name="mnp_style" />
<attr name="android:background" />
<attr name="android:orientation" />
</declare-styleable>
<declare-styleable name="MaterialNumberPickerFloat">
<attr name="mnp_valueFloat" format="float" />
<attr name="mnp_stepSizeFloat" format="float" />
<attr name="mnp_stepSizeLargeFloat" format="float" />
<attr name="mnp_minFloat" format="float" />
<attr name="mnp_maxFloat" format="float" />
<attr name="mnp_prefix" />
<attr name="mnp_suffix" />
<attr name="mnp_editTextStyle" />
<attr name="mnp_buttonWidth" />
<attr name="mnp_iconUp" />
<attr name="mnp_iconDown" />
<attr name="mnp_iconUpLarge" />
<attr name="mnp_iconDownLarge" />
<attr name="mnp_longPressRepeatClicks" />
<attr name="mnp_orientation" />
<attr name="mnp_style" />
<attr name="mnp_commas" format="integer" />
<attr name="android:background" />
<attr name="android:orientation" />
</declare-styleable>
<attr name="pickerStyle" format="reference" />
</resources>
Question
As you can see, I've defined shared attributes like mnp_prefix and mnp_suffix which is easy because they are strings for both views. As you can image, a number picker has a value, so I defined a mnp_valueInt for the integer number picker and mnp_valueFloat for the float number picker - what I would prefer though is to define mnp_float in both views but with different formats - inter or float, depending on the picker type. BUT if I do this, I get compilation errors because mnp_value is defined multiple times. Is there a more beautiful solution than mine for this problem?
I have an android application where I make use of a custom font, let's call it my_font.ttf which I have saved in my font folder in the res package.
I also have a custom number picker where I need to set the font for the values in the picker. This is my attrs.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="NumPicker">
<attr name="max" format="integer" />
<attr name="min" format="integer" />
<attr name="selectedTextColor" format="color" />
<attr name="selectedTextSize" format="float" />
<attr name="textColor" format="color" />
<attr name="textSize" format="dimension" />
<attr name="typeface" format="enum">
<enum name="font" value="0"/>
<enum name="sans" value="1"/>
<enum name="serif" value="2"/>
<enum name="monospace" value="3"/>
</attr>
</declare-styleable>
</resources>
I want to know how I can add my_font.ttf into this attrs.xml so that I can use it in my layout file to set the font. Like those serif, sans, monospace ones work as they are built in fonts, but I am not sure how to use my font.
Here is my layout file which makes use of the custom NumPicker:
<com.myproject.slidertest.selectors.numberpicker.NumPicker
android:id="#+id/numberPicker"
android:layout_width="wrap_content"
android:layout_height="300dp"
android:paddingLeft="40dp"
android:paddingRight="40dp"
android:layout_gravity="center_horizontal"
app:typeface="serif"<!-- I want to be able to change this font to my font-->
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:selectedTextColor="#color/color_blue"
app:textColor="#color/colorTextDefault"
app:max="50"
app:min="10"
/>
Any help or advice will be highly appreciated.
Add another attr
<attr fontTextAppearance format="reference">
In the custom view, if the typeface type is font, look for the typefaceFont reference.
val textAppearance = ta.getResourceId(R.styleable.NumPicker_fontTextAppearance, -1)
if (textAppearance != -1) {
textView.setTextAppearance(textAppearance)
}
<com.myproject.slidertest.selectors.numberpicker.NumPicker
android:id="#+id/numPicker"
style="#style/NumPicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:fontTextAppearance="#style/NumPickerFont"
/>
<style name="NumPickerFont">
<item name="android:textColor">#color/white</item>
<item name="android:textSize">40sp</item>
<item name="android:textAlignment">viewStart</item>
<item name="android:letterSpacing">0.18</item>
<item name="android:fontFamily">#font/some_font</item>
</style>
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
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.
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.