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();
}