Подтвердить что ты не робот

Android: несколько представлений для пользовательского представления с существующим макетом

Мне нужно создать более сложный пользовательский вид в Android. Окончательный макет должен выглядеть следующим образом:

<RelativeLayout>
  <SomeView />
  <SomeOtherView />
  <!-- maybe more layout stuff here later -->
  <LinearLayout>
    <!-- the children -->
  </LinearLayout>
</RelativeLayout>

Однако в файлах XML я просто хочу определить это (без указания SomeView, SomeOtherView и т.д.):

<MyCustomView>
  <!-- the children -->
</MyCustomView>

Возможно ли это в Android, и если да: какой был бы самый чистый способ сделать это? Возможные решения, которые пришли мне на ум, были "переопределить методы addView()" и "удалить все представления и добавить их позже", но я не уверен, куда идти...

Большое спасибо за вашу помощь!:)

4b9b3361

Ответ 1

Совершенно возможно и рекомендуется создавать пользовательские представления контейнеров. Это то, что Android назвал бы составным элементом управления. Итак:

public class MyCustomView extends RelativeLayout {
    private LinearLayout mContentView;

    public MyCustomView(Context context) {
        this(context, null);
    }

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

    public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        //Inflate and attach your child XML
        LayoutInflater.from(context).inflate(R.layout.custom_layout, this);
        //Get a reference to the layout where you want children to be placed
        mContentView = (LinearLayout) findViewById(R.id.content);

        //Do any more custom init you would like to access children and do setup
    }

    @Override
    public void addView(View child, int index, ViewGroup.LayoutParams params) {
        if(mContentView == null){
            super.addView(child, index, params);
        } else {
            //Forward these calls to the content view
            mContentView.addView(child, index, params);
        }
    }
}

Вы можете переопределить столько версий addView(), сколько хотите, но в конце концов все они возвращаются к версии, помещенной в образец. Переопределение только этого метода будет иметь рамки, которые передают всем дочерним элементам, находящимся внутри его тега XML, в конкретный дочерний контейнер.

И затем измените XML как таковой:

Рез/макет/custom_layout.xml

<merge>
  <SomeView />
  <SomeOtherView />
  <!-- maybe more layout stuff here later -->
  <LinearLayout
      android:id="@+id/content" />
</merge>

Причиной использования <merge> является упрощение иерархии. Все дочерние представления привязаны к вашему пользовательскому классу, который является RelativeLayout. Если вы не используете <merge>, вы получите RelativeLayout, прикрепленный к другому RelativeLayout, прикрепленному ко всем дочерним элементам, что может вызвать проблемы.

НТН

Ответ 2

вы можете использовать тег include

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical">
    <include android:id="@+id/nav_bar_layout" layout="@layout/nav_bar" android:layout_above="@+id/web_view" />
    <WebView android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/web_view" android:layout_centerInParent="true" />
    <include android:id="@+id/admob_layout" layout="@layout/admob_layout" android:layout_below="@+id/web_view" />
</RelativeLayout>