1

I create a custom view with few views inside it.

I want to set a custom Attribute to set its style.

How can i do it grammatically as I'm not creating the inner views dynamically but from xml.

I see you can set style grammatically only when creating the view via code (and not via xml) ?

RelativeLayout someLayout = new RelativeLayout(context, null, R.style.LightStyle);

https://stackoverflow.com/a/21043373/311130

Elad Benda
  • 35,076
  • 87
  • 265
  • 471

1 Answers1

0

I'd like to propose a couple of possible solutions, however they are not completely flawless, because of design of this part in Android

Configuring inner view via code

There is no way to wrap an inner TypedArray as an argument of another TypedArray and I don't think it's a reasonable way to make an instance of the AttrbiteSet (that is supposed to go under this parameter) in the code to set up a view. Instead just use default constructor new RelativeLayout(context) without xml attributes and provide all required values yourself (you still can declare a custom attributes in your declare-styleable resource to leverage XML-based styling, and use them as part of your inner views, but it will be your 'manual' setup). The justification is as follow:

  • AttributeSet isn't designed to be built in code. Check the documents and you will see that the only implementation of this interface is the XmlResourceParser.
  • The Android code itself does not build this parameter in code even when it may be reasonable. For example here is the first lines of the code of the constructor of the View(Context context) class:

    public View(Context context) {
            mContext = context;
            mResources = context != null ? context.getResources() : null;
            mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED | FOCUSABLE_AUTO;
            ...
            setOverScrollMode(OVER_SCROLL_IF_CONTENT_SCROLLS);
            mUserPaddingStart = UNDEFINED_PADDING;
            mUserPaddingEnd = UNDEFINED_PADDING;
            ...
    }

    As you can see there is no cases when Xml attributes are made programatically, but instead the corresponding values are set in code.

Configuring inner view via external layout

You can make a custom attribute that is pointing to an external layout, that should be compatible with the inner view your are using. Unfortunately i don't know if there is a way to restrict type of this layout, so a consumer of your class can provide whatever reference he wants, and only you can do here is throwing a runtime exception to let him be aware that something is wrong. In your custom view styleable attributes declare a custom reference attribute:

<resources>
    <declare-styleable name="CustomView">
        <attr name="inner_layout" format="reference" />
    </declare-styleable>
</resources>

In your custom view constructor inflate desired layout using retrieved layout id:

TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.CustomView, defStyle, 0);

try {
    int resource = a.getResourceId(R.styleable.CustomView_inner_layout, 0);
    RelativeLayout layout = LayoutInflater.from(context).inflate(resource, this, false);
} finally {
    a.recycle();
} 
The Dreams Wind
  • 8,416
  • 2
  • 19
  • 49