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>