Skip to content

View Proxies

Nathanael Silverman edited this page Aug 18, 2018 · 2 revisions

Ordinarily views are made styleable by annotating their class directly. However that's only possible when the class is editable. What about view classes provided by Android or third-party libraries? For those Paris uses "view proxies."

Let's look at an excerpt from Paris' own codebase which uses a view proxy to support TextView styles. First, we create an attribute list like we would for a custom view:

<declare-styleable name="Paris_TextView">
    <attr name="android:text" />
    ...
</declare-styleable>

In this case the attribute is already defined by Android so we don't specify the format.

Then we create a new proxy class whose sole purpose is to map attribute values to the view. All proxy classes must extend BaseProxy<P, V> where P is the Proxy's own type and V is the view type that's being proxies.

@Styleable("Paris_TextView")
class TextViewProxy(view: TextView) : BaseProxy<TextViewProxy, TextView>(view) {

    @Attr(R2.styleable.Paris_TextView_android_text)
    fun setText(text: CharSequence?) {
        view.text = text
    }

    ...
}
Click to see the example in Java.
@Styleable("Paris_TextView")
public class TextViewProxy extends BaseProxy<TextViewProxy, TextView> {

    public TextViewProxy(TextView view) {
        super(view);
    }

    @Attr(R2.styleable.Paris_TextView_android_text)
    public void setText(CharSequence text) {
        getView().setText(text);
    }

    ...
}

Proxies must declare a constructor that receives the view to be proxied as a single parameter and passes it to the parent. The view can be accessed through view to forward attribute values.

Everything else works just like custom views:

  • The class must be annotated with @Styleable
  • Methods annotated with @Attr are called when a style is applied
  • All other annotations work as expected (@BeforeStyle, @AfterStyle, @Style...)

Proxy instances are created when the view is about to be restyled and discarded afterwards. They are not reused.

Note: The view might be an instance of that view type or a descendant.