Custom views can also take custom attributes which can be used in Android layout resource files. To add attributes to your custom view you need to do the following:
Define the name and type of your attributes: this is done inside res/values/attrs.xml
(create it if necessary). The following file defines a color attribute for our smiley's face color and an enum attribute for the smiley's expression:
<resources>
<declare-styleable name="SmileyView">
<attr name="smileyColor" format="color" />
<attr name="smileyExpression" format="enum">
<enum name="happy" value="0"/>
<enum name="sad" value="1"/>
</attr>
</declare-styleable>
<!-- attributes for other views -->
</resources>
Use your attributes inside your layout: this can be done inside any layout files that use your custom view. The following layout file creates a screen with a happy yellow smiley:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent">
<com.example.app.SmileyView
android:layout_height="56dp"
android:layout_width="56dp"
app:smileyColor="#ffff00"
app:smileyExpression="happy" />
</FrameLayout>
Tip: Custom attributes do not work with the tools:
prefix in Android Studio 2.1 and older (and possibly in future versions). In this example, replacing app:smileyColor
with tools:smileyColor
would result in smileyColor
neither being set during runtime nor at design time.
Read your attributes: this is done inside your custom view source code. The following snippet of SmileyView
demonstrates how the attributes can be extracted:
public class SmileyView extends View {
// ...
public SmileyView(Context context) {
this(context, null);
}
public SmileyView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SmileyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SmileyView, defStyleAttr, 0);
mFaceColor = a.getColor(R.styleable.SmileyView_smileyColor, Color.TRANSPARENT);
mFaceExpression = a.getInteger(R.styleable.SmileyView_smileyExpression, Expression.HAPPY);
// Important: always recycle the TypedArray
a.recycle();
// initPaints(); ...
}
}
(Optional) Add default style: this is done by adding a style with the default values and loading it inside your custom view. The following default smiley style represents a happy yellow one:
<!-- styles.xml -->
<style name="DefaultSmileyStyle">
<item name="smileyColor">#ffff00</item>
<item name="smileyExpression">happy</item>
</style>
Which gets applied in our SmileyView
by adding it as the last parameter of the call to obtainStyledAttributes
(see code in step 3):
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SmileyView, defStyleAttr, R.style.DefaultSmileyViewStyle);
Note that any attribute values set in the inflated layout file (see code in step 2) will override the corresponding values of the default style.
(Optional) Provide styles inside themes: this is done by adding a new style reference attribute which can be used inside your themes and providing a style for that attribute. Here we simply name our reference attribute smileyStyle
:
<!-- attrs.xml -->
<attr name="smileyStyle" format="reference" />
Which we then provide a style for in our app theme (here we just reuse the default style from step 4):
<!-- themes.xml -->
<style name="AppTheme" parent="AppBaseTheme">
<item name="smileyStyle">@style/DefaultSmileyStyle</item>
</style>