Дети расширенного LinearLayout, определенные в XML, не отображаются

В моем проекте есть экраны, на которых часто повторяется один и тот же шаблон — это в основном контейнер для представлений, состоящий из линейного макета с заголовком, изображением и определенным фоном. Чтобы избежать многократного копирования и вставки одной и той же последовательности, я подумал, что могу создать составное представление, расширить LinearLayout и определить там все «стили», а затем просто использовать этот компонент в своих макетах. Я следовал инструкциям и примерам, и мой составной вид заработал. Однако все примеры, которые я видел, используют результирующее представление следующим образом:

<com.myproject.compound.myview
    ...some attrs...
/>

т.е. никакие дети не добавляются через XML. Мне нужно использовать это так:

<com.myproject.compound.myview
    ...some attrs...>
    <TextView 
        ..../>
    ...other views...

</com.myproject.compound.myview>

Поскольку я расширяю LinearLayout, я ожидал, что тег «myview» будет работать так же, как LinearLayout, но по какой-то причине элементы, которые я помещаю внутрь, не отображаются. Есть ли что-то, что мне нужно сделать специально, чтобы получить внутренние виды для рисования?

Мой расширенный LinearLayout очень прост, я не переопределяю какие-либо методы, а просто вызываю super в конструкторе и раздуваю макет следующим образом:

    LayoutInflater inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.my_compound_view, this, true);

ОБНОВЛЕНИЕ: я подумал, что добавлю XML в качестве ориентира:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" 
android:background="@drawable/bg"
android:padding="12dp">
<TextView 
    android:id="@+id/section_title"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textColor="#FF0000AA"        />
<ImageView
    android:layout_width="match_parent"
    android:layout_height="2dp"
        android:src="@drawable/line"        />
</LinearLayout>

person Dennis K    schedule 18.03.2013    source источник


Ответы (2)


На самом деле нашел более элегантное решение. Просто нужно использовать тег слияния вместо LinearLayout в составном представлении. Все сводится к:

<merge xmlns:android="http://schemas.android.com/apk/res/android"
    <TextView 
        android:id="@+id/section_title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="HEADING"
        android:textColor="#FF0000AA"        />
    <ImageView
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:src="@drawable/line"        />
</merge>

а также

public class CompoundLayout extends LinearLayout{
    public CompoundLayout(Context context, AttributeSet attrs) {
        super(context, attrs);

        LayoutInflater inflater = (LayoutInflater) context
           .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        inflater.inflate(R.layout.compound_layout, this, true);
    }
}

Основной макет:

<com.testbench.CompoundLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#FFFFDDEE"
    android:orientation="vertical">
    <TextView 
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Inner text"
            android:layout_gravity="center_horizontal"/>        
</com.testbench.CompoundLayout>
person Dennis K    schedule 20.03.2013

Прочитав исходный код и примеры Android, я думаю, что понял это. По сути, в моем случае это гибрид Compound View и Custom Layout. Часть «Составное представление» отвечает за разметку и отрисовку содержимого XML, который определяет «контейнер». Но элементы внутри этого контейнера позже раздуваются, и в моей реализации они не выкладываются. Один из способов - следовать пути пользовательского макета - мне пришлось бы реализовать onLayout() и onMeasure(), чтобы правильно вычислить моих детей (и я сделал это во время своего исследования, это сработало). Но так как мне действительно не нужно ничего отличного от того, что уже делает LinearLayout, и я не хочу копировать/вставлять его код (эти методы там огромны), я просто решил переопределить метод onFinishInflate() и добавил свой «представление контейнера». " там. Вот весь код, пожалуйста, прокомментируйте, что-то можно улучшить.

public class CompoundLayout extends LinearLayout{
View mView;
public CompoundLayout(Context context, AttributeSet attrs) {
    super(context, attrs);

    LayoutInflater inflater = (LayoutInflater) context
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        mView = inflater.inflate(R.layout.compound_layout, this, false);
}

@Override
public void onFinishInflate(){
    super.onFinishInflate();
    addView(mView, 0);
}
}

Затем в основном макете Activity я просто использую свой собственный макет так же, как использовал бы LinearLayout. Он отображает то же самое, но всегда с этими TextView и ImageView сверху.

person Dennis K    schedule 19.03.2013