Skip to content

How do I...

Nathanael Silverman edited this page Oct 24, 2018 · 2 revisions

This page answers common how-to questions that may come up when using Paris. You should read and understand the Overview and the Core documentation first.

Contents

… extend a @Styleable class?

Nothing tricky here, extending views annotated with @Styleable should just work.

@Styleable("MyView")
open class MyView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : View(context, attrs, defStyleAttr) {

    init {
        style(attrs)
    }

    …
}

@Styleable("MyViewExtension")
class MyViewExtension @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = 0
) : MyView(context, attrs, defStyleAttr) {

    init {
        // Every view in the hierarchy needs to call this for itself.
        style(attrs)
    }

    …
}
Click to see the example in Java.
@Styleable("MyView")
public class MyView extends View {

    public MyView(Context context) {
        super(context);
    }

    public MyView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyView(Context context, AttributeSet attrs, int defStyle) {
        this(context, attrs, defStyle);
        Paris.style(this).apply(attrs);
    }

    ...
}

@Styleable("MyViewExtension")
public class MyViewExtension extends MyView {
    
    public MyViewExtension(Context context) {
        super(context);
    }

    public MyViewExtension(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MyViewExtension(Context context, AttributeSet attrs, int defStyle) {
        this(context, attrs, defStyle);
        // Every view in the hierarchy needs to call this for himself
        Paris.style(this).apply(attrs);
    }

    ...
}

Each view in the hierarchy needs to call style(attrs) during initialization.

However when using myViewExtension.style(R.style…) with a style resource all attributes throughout the view hierarchy will be applied (from MyViewExtension, MyView, and View). Similarly when using a style builder all attribute methods throughout the view hierarchy will be available.

… apply a style to a subview's subview?

As we've seen, Paris generates helper methods to style annotated subviews:

@Styleable("MyView")
class MyView(…) : View(…) {

    @StyleableChild(R.styleable.MyView_labelStyle)
    internal val label: TextView by lazy { findViewById(R.id…) }
}

// Applying a style to a MyView instance.
myView.style(R.style…)
// Applying a style to the label.
myView.style {
    labelStyle(R.style…)
}
Click to see the example in Java.
@Styleable("MyView")
public class MyView extends View {

    @StyleableChild(R.styleable.MyView_labelStyle)
    TextView label;
}

// Applying a style to a MyView instance.
Paris.style(myView).apply(R.style…);
// Applying a style to the label.
Paris.styleBuilder(myView)
        .labelStyle(R.style…)
        .apply();

But what if the subview has styleable subviews of its own? Paris lets you chain calls so you can style any annotated subview in the hierarchy:

@Styleable("MyHeader")
class MyHeader(…) : ViewGroup(…) {

    @StyleableChild(R.styleable.MyHeader_myViewStyle)
    internal val myView: MyView …

    @StyleableChild(R.styleable.MyHeader_titleStyle)
    internal val title: TextView …
}

// Applying a style to a MyHeader instance.
myHeader.style(R.style…)
// Applying a style to the MyView subview.
myHeader.style {
    myViewStyle(R.style…)
}
// Applying a style to MyView's label.
myHeader.style {
    myViewStyle {
        labelStyle(R.style…)
    }
}
Click to see the example in Java.
@Styleable("MyHeader")
public class MyHeader extends ViewGroup {

    @StyleableChild(R.styleable.MyHeader_myViewStyle)
    MyView myView;

    @StyleableChild(R.styleable.MyHeader_titleStyle)
    TextView title;
}

// Applying a style to a MyHeader instance.
Paris.style(myHeader).apply(R.style…);
// Applying a style to the MyView subview.
Paris.style(myHeader)
        .myViewStyle(R.style…)
        .apply();
// Applying a style to MyView's label.
Paris.style(myHeader)
        .myViewStyle((builder) -> builder
                .labelStyle(R.style…)
        )
        .apply();

… add support for an Android view attribute?

Support for Android view attributes can be added using View Proxies.