Я хотел бы предложить несколько возможных решений, однако они не являются абсолютно безупречными из-за дизайна этой части в Android
Настройка внутреннего вида с помощью кода
Нет способа обернуть внутренний TypedArray
в качестве аргумента другого TypedArray
, и я не думаю, что это разумный способ сделать экземпляр AttrbiteSet
(то есть должен идти под этим параметром) в коде, чтобы настроить представление. Вместо этого просто используйте конструктор по умолчанию new RelativeLayout(context)
без атрибутов xml и предоставьте все необходимые значения самостоятельно (вы все равно можете объявить пользовательские атрибуты в своем ресурсе declare-styleable
для использования стилей на основе XML и использовать их как часть ваших внутренних представлений, но это будет вашей «ручной» настройкой). Обоснование таково:
AttributeSet
не предназначен для встроенного кода. Проверить
документы, и вы увидите, что единственная реализация этого
интерфейс XmlResourceParser
.
Сам код Android
не встраивает этот параметр в код, даже если он может быть разумным.
Например, вот первые строки кода конструктора
View(Context context)
класс:
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;
...
}
Как видите, не бывает случаев, когда атрибуты XML создаются программно, но вместо этого соответствующие значения задаются в коде.
Настройка внутреннего вида с помощью внешнего макета
Вы можете создать пользовательский атрибут, который указывает на внешний макет, чтобы должен был быть совместимым с внутренним представлением, которое вы используете. К сожалению, я не знаю, есть ли способ ограничить тип этого макета, поэтому потребитель вашего класса может предоставить любую ссылку, которую он хочет, и только вы можете сделать здесь - выбросить исключение времени выполнения, чтобы он знал, что что-то неправильно.
В настраиваемом представлении настраиваемых атрибутов объявите настраиваемый ссылочный атрибут:
<resources>
<declare-styleable name="CustomView">
<attr name="inner_layout" format="reference" />
</declare-styleable>
</resources>
В конструкторе пользовательского представления надуйте желаемый макет, используя полученный идентификатор макета:
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();
}