When developing
HoloEverywhere I ran into the fact that most of the questions sent to me somehow relate to how to stylize any widgets.
That is, the people do not particularly understand the principle of how themes and attributes work.
Let's try a little chew on this topic.
For a start: what are all styles? A set of values for attributes.
And where is the list of these attributes, how to get their values?
Styleable resources.
')
Let's take the old-fashioned way: create your own view:
package habra.tutorial.customwidget; import android.content.Context; import android.util.AttributeSet; import android.view.View; public class HabraWidget extends View { public HabraWidget(Context context) { super(context); } public HabraWidget(Context context, AttributeSet attrs) { super(context, attrs); } public HabraWidget(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } }
Have you ever wondered what the last, third, argument is in the constructor? int defStyle?
You will have time to think, and for the time being we will create our first attribute, the value of which will lie in the theme for the Activity or even for the entire application ...
Create values / attrs.xml (the name is not important, you can even in strings.xml)
<?xml version="1.0" encoding="utf-8"?> <resources> <attr name="habraWidgetStyle" format="reference" /> </resources>
In Android, attribute names for styles for widgets are usually set with the widget name in camelCase + style Postfix.
And format sets, oddly enough, the format of values. Let's leave the reference here, i.e. link to the resource, in this case - to the style.
Now we modify the constructors of our widget. Now they just call the parent constructor.
And now the feature defStyle - it sets the name of the attribute, by default, the values from the style referenced by this attribute will be used.
public HabraWidget(Context context) { this(context, null); } public HabraWidget(Context context, AttributeSet attrs) { this(context, attrs, R.attr.habraWidgetStyle); }
Those. the HabraWidget (Context) constructor will call HabraWidget (Context, AttributeSet) with the second argument null,
and he in turn calls HabraWidget (Context, AttributeSet, int) with our attribute.
Now we define, and what, in fact, our widget will do? Let him draw a simple cross from his corners:
private final Paint paint; public HabraWidget(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); paint = new Paint(); paint.setColor(0xFF00EEFF); paint.setStyle(Style.FILL_AND_STROKE); } @Override protected void onDraw(Canvas canvas) { canvas.drawLine(0, 0, getWidth(), getHeight(), paint); canvas.drawLine(getWidth(), 0, 0, getHeight(), paint); }
Great, but the color of the line is strictly specified in the code (0xFF00EEFF), are you thinking about the same thing, what am I talking about? Bring in styles!
First, create a styleable with an attribute ... well, let's say, lineColor:
attrs.xml
<declare-styleable name="HabraWidget"> <attr name="lineColor" format="color|reference"/> </declare-styleable>
And create the default style:
styles.xml
<style name="HabraWidget"> <item name="lineColor">#f00</item> </style>
And now how to get the color out?
TypedArray:
public HabraWidget(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.HabraWidget, defStyle, R.style.HabraWidget); paint = new Paint(); paint.setColor(a.getColor(R.styleable.HabraWidget_lineColor, 0xFFFF0000)); paint.setStyle(Style.FILL_AND_STROKE); a.recycle(); }
0xFFFF0000 - default color. You can also transfer any zero, since we have indicated the default theme.
Well, do not forget to recycle after you have pulled out all the data.
Further feature related to the creation of layout. We are used to the fact that all attributes are set through the namespace android :.
But since our attributes are not in the android package, then another namespace will be.
I will give an example:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:habra="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <habra.tutorial.customwidget.HabraWidget android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" habra:lineColor="#00f" /> <habra.tutorial.customwidget.HabraWidget android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" habra:lineColor="#0f0" /> </LinearLayout>

Now we can freely set the color of the lines from the markup.