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()" и "удалить все представления и добавить их позже", но я не уверен, какой путь выбрать...
Заранее большое спасибо за вашу помощь!:)
2 ответа
Абсолютно возможно и рекомендуется создавать пользовательские представления контейнеров. Это то, что 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
привязан ко всем детям, что может вызвать проблемы.
НТН
Вы можете использовать тег включения
<?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>