java - programacion - Android: escritura de un componente personalizado(compuesto)
manual de programacion android pdf (2)
Creo que la forma en que se supone que debes hacerlo es usar tu nombre de clase como el elemento raíz XML:
<com.example.views.MyView xmlns:....
android:orientation="vertical" etc.>
<TextView android:id="@+id/text" ... />
</com.example.views.MyView>
Y luego haz que tu clase se derive del diseño que quieras usar. Tenga en cuenta que si está utilizando este método , no usa el inflador de diseño aquí.
public class MyView extends LinearLayout
{
public ConversationListItem(Context context, AttributeSet attrs)
{
super(context, attrs);
}
public ConversationListItem(Context context, AttributeSet attrs, int defStyle)
{
super(context, attrs, defStyle);
}
public void setData(String text)
{
mTextView.setText(text);
}
private TextView mTextView;
@Override
protected void onFinishInflate()
{
super.onFinishInflate();
mTextView = (TextView)findViewById(R.id.text);
}
}
Y luego puede usar su vista en diseños XML de forma normal. Si desea hacer la vista mediante programación, debe inflarla usted mismo:
MyView v = (MyView)inflater.inflate(R.layout.my_view, parent, false);
Desafortunadamente, esto no le permite hacer v = new MyView(context)
porque no parece haber una forma de solucionar el problema de diseños anidados, por lo que esta no es una solución completa. Podría agregar un método como este a MyView
para hacerlo un poco más agradable:
public static MyView create(Context context)
{
return (MyView)LayoutInflater.fromContext(context).inflate(R.layout.my_view, null, false);
}
Descargo de responsabilidad: es posible que esté hablando tonterías completas.
La aplicación de Android que estoy desarrollando actualmente tiene una actividad principal que ha crecido bastante. Esto se debe principalmente a que contiene un TabWidget
con 3 pestañas. Cada pestaña tiene bastantes componentes. La actividad tiene que controlar todos esos componentes a la vez. Así que creo que puedes imaginar que esta actividad tiene como 20 campos (un campo para casi todos los componentes). También contiene mucha lógica (haga clic en oyentes, lógica para llenar listas, etc.).
Lo que normalmente hago en los marcos basados en componentes es dividir todo en componentes personalizados. Cada componente personalizado tendría una responsabilidad clara. Contendría su propio conjunto de componentes y toda otra lógica relacionada con ese componente.
Traté de descubrir cómo se puede hacer esto, y encontré algo en la documentación de Android a lo que les gusta llamar un "control compuesto". (Consulte http://developer.android.com/guide/topics/ui/custom-components.html#compound y vaya a la sección "Compound Controls") Me gustaría crear dicho componente en base a un archivo XML que defina el ver estructura.
En la documentación dice:
Tenga en cuenta que al igual que con una actividad, puede usar el enfoque declarativo (basado en XML) para crear los componentes contenidos, o puede anidarlos programáticamente desde su código.
Bueno, ¡esas son buenas noticias! ¡El enfoque basado en XML es exactamente lo que quiero! Pero no dice cómo hacerlo, excepto que es "como con una actividad" ... Pero lo que hago en una actividad es llamar a setContentView(...)
para inflar las vistas desde XML. Ese método no está disponible si, por ejemplo, subclase LinearLayout
.
Así que traté de inflar el XML manualmente de esta manera:
public class MyCompoundComponent extends LinearLayout {
public MyCompoundComponent(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.my_layout, this);
}
}
Esto funciona, excepto por el hecho de que el XML que estoy cargando ha declarado a LinearLayout
como el elemento raíz. ¡Esto da como resultado que el inflado LinearLayout
sea un elemento secundario de MyCompoundComponent
que ya es un LinearLayout
! Entonces ahora tenemos LinearLayout redundante entre MyCompoundComponent
y las vistas que realmente necesita.
¿Puede alguien proporcionarme una mejor manera de abordar esto, evitando tener una LinearLayout
redundante instanciada?
Use la etiqueta merge como su raíz XML
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Your Layout -->
</merge>