layout_width layout_weight examples ejemplo dinamico constraint android android-layout

android - layout_weight - ¿Cómo inflar XML-Layout-File correctamente dentro de Custom ViewGroup?



table layout android (5)

Quiero inflar un XML-Layout-File en una clase de ViewGroup personalizada, mi problema es que produce solo una pantalla vacía. Hacer lo mismo en la clase de actividad funciona bien. Aquí está mi simple XML-Layout-File:

shownumberlayout.xml: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="#FFFFFF" android:id="@+id/layoutForNumber"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/tvNumber" android:layout_centerHorizontal="true" android:textColor="#000000" android:text="Test" android:layout_centerVertical="true" android:textSize="30dip"> </TextView> </RelativeLayout>

Aquí está la Versión de trabajo, inflando el shownumberlayout.xml en el Activity ShowNumber :

ShowNumber.class public class ShowNumber extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LayoutInflater inflater = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE); ViewGroup vg = (ViewGroup) inflater.inflate(R.layout.shownumberlayout, null); setContentView(vg); } }

Esto muestra un fondo blanco con el texto negro "Test" centrado.

Ahora la Versión inflar el xml en el Custom ViewGroup -Class:

ViewGroup.class public class ViewNumber extends ViewGroup { private LayoutInflater inflater; public ViewNumber(Context context) { super(context); // TODO Auto-generated constructor stub initView(context); } public ViewNumber(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub initView(context); } public ViewNumber(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); // TODO Auto-generated constructor stub initView(context); } private void initView(Context context){ inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); inflater.inflate(R.layout.shownumberlayout, null); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // TODO Auto-generated method stub } }

ShowNumber.class public class ShowNumber extends Activity {/ ** Llamada cuando la actividad se crea por primera vez. * /

@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ViewGroup vg = new ViewNumber(this); setContentView(vg); }

}

Lo estoy haciendo básicamente como en this Respuesta explicada. Esto solo produce una Pantalla Negra Vacía. ¿Que estoy haciendo mal?

ACTUALIZACIÓN 1

@Konstantin Apliqué tus cambios pero solo una pantalla en blanco, también hice una salida de registro para obtener el número de hijos. Siempre permanece 1, incluso agrego una Textview más al XML-Layout-File. Antes de los cambios, siempre permanece 0.

public class ViewNumber extends RelativeLayout { ... private void initView(Context context){ //inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); //inflater.inflate(R.layout.shownumberlayout, null); View.inflate(context, R.layout.shownumberlayout,this); Log.v("ViewNumber", "Number of Child: " + this.getChildCount());//output is 1,before it remains 0 } ... }

@Sankar Este es el Logcat, después de los cambios de Konstantin:

12-16 09:24:23.606: DEBUG/AndroidRuntime(8951): >>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<< 12-16 09:24:23.606: DEBUG/AndroidRuntime(8951): CheckJNI is OFF 12-16 09:24:23.606: DEBUG/dalvikvm(8951): creating instr width table 12-16 09:24:23.656: DEBUG/AndroidRuntime(8951): --- registering native functions --- 12-16 09:24:23.916: DEBUG/AndroidRuntime(8951): Shutting down VM 12-16 09:24:23.916: DEBUG/dalvikvm(8951): Debugger has detached; object registry had 1 entries 12-16 09:24:23.916: INFO/AndroidRuntime(8951): NOTE: attach of thread ''Binder Thread #3'' failed 12-16 09:24:24.076: DEBUG/AndroidRuntime(8960): >>>>>>>>>>>>>> AndroidRuntime START <<<<<<<<<<<<<< 12-16 09:24:24.076: DEBUG/AndroidRuntime(8960): CheckJNI is OFF 12-16 09:24:24.076: DEBUG/dalvikvm(8960): creating instr width table 12-16 09:24:24.126: DEBUG/AndroidRuntime(8960): --- registering native functions --- 12-16 09:24:24.376: INFO/ActivityManager(78): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=org.customview.harold/.ShowNumber } 12-16 09:24:24.426: DEBUG/AndroidRuntime(8960): Shutting down VM 12-16 09:24:24.426: DEBUG/jdwp(8960): Got wake-up signal, bailing out of select 12-16 09:24:24.426: DEBUG/dalvikvm(8960): Debugger has detached; object registry had 1 entries 12-16 09:24:24.456: INFO/AndroidRuntime(8960): NOTE: attach of thread ''Binder Thread #3'' failed 12-16 09:24:24.456: VERBOSE/ViewNumber(8923): Number of Child: 1 12-16 09:24:24.496: VERBOSE/RenderScript_jni(164): surfaceDestroyed 12-16 09:24:24.526: INFO/ActivityManager(78): Displayed activity org.customview.harold/.ShowNumber: 104 ms (total 104 ms) 12-16 09:24:24.576: DEBUG/dalvikvm(158): GC_FOR_MALLOC freed 10631 objects / 526248 bytes in 52ms 12-16 09:24:34.606: DEBUG/dalvikvm(164): GC_EXPLICIT freed 1776 objects / 106960 bytes in 91ms

ACTUALIZACIÓN 2

El contenido finalmente se muestra correctamente. Lo que faltaba era anular el Método en onLayout (gracias a Franco ) en RelativeLayout-Sublcass:

public class ViewNumber extends RelativeLayout { ... @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // TODO Auto-generated method stub for(int i = 0 ; i < getChildCount() ; i++){ getChildAt(i).layout(l, t, r, b); } } ... }

Nota: Más tarde también debe anular el Método en la onMeasurement() , pero actualmente el contenido también se muestra correctamente sin anularlo.

Ahora la solución para el Método initView de Franco no alinea el TextView en el Centro, sino que lo coloca en la esquina superior izquierda. La solución de Konstantin lo coloca correctamente en el centro de la vista:

public class ViewNumber extends RelativeLayout { ... private void initView(Context context){ View.inflate(context, R.layout.shownumberlayout,this); } ... }


¿Has intentado esto?

private void initView(Context context){ inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); this.addView(inflater.inflate(R.layout.shownumberlayout, null)); }

EDITAR: Respondo rápidamente ... un ViewGroup tiene la responsabilidad de preparar el diseño para sus hijos, en el método de diseño intente esto:

@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // TODO Auto-generated method stub for(int i = 0 ; i < getChildCount() ; i++){ getChildAt(i).layout(l, t, r, b); } }


No sé qué está pasando en estas respuestas ... Creo que llamar a onLayout manualmente está un poco loco.

La función LayoutInflater.inflate es bastante directa. Si está utilizando el que acepta el tercer argumento booleano (attachToRoot) y es verdadero , agregará las vistas de su XML a su vista principal (el segundo argumento). Si está utilizando el que acepta solo 2 argumentos, pasará true a attachToRoot de forma predeterminada si proporciona un elemento primario que no sea nulo .

En cualquier caso, la mayor parte del problema que está experimentando se debe a que las vistas de su XML se agregan a su vista personalizada. Dado que su XML tiene una raíz RelativeLayout y su vista personalizada también es RelativeLayout , obtendrá un diseño relativo dentro de un diseño relativo.

Esto probablemente no es lo que quieres.

La respuesta dada por Konstantin tiene sentido, pero estás desperdiciando una vista porque estás colocando un RelativeLayout dentro de FrameLayout . Como Android no puede contener demasiadas vistas anidadas, es una buena idea optimizar y no agregar este FrameLayout innecesario.

Sugiero mantener su vista personalizada como RelativeLayout y cambiar su raíz XML a <merge> . A continuación, utilice el formulario de View.inflate(context,int,this) que agrega las vistas XML a su elemento primario, como View.inflate(context,int,this)

El objetivo de la etiqueta <merge> es omitir el nodo raíz en el XML. Búsquelo.


Prueba este:

LayoutInflater inflater = (LayoutInflater) context.getSystemService( Context.LAYOUT_INFLATER_SERVICE ); inflater.inflate( R.layout.login_view_layout, null );


Su diseño está inflado en ninguna parte ... haga que su ViewNumber amplíe FrameLayout e infle en él:

public class ViewNumber extends FrameLayout { public ViewNumber(Context context) { super(context); initView(context); } public ViewNumber(Context context, AttributeSet attrs) { super(context, attrs); initView(context); } public ViewNumber(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initView(context); } private void initView(Context context){ View.inflate(context, R.layout.shownumberlayout, this); //correct way to inflate.. } }

UPD: tampoco es necesario que anule el método de encendido, que se ve muy incorrecto ... al menos llame a super.onLayout () desde el principio:

@Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); }


onLayout es necesario. Cuando crea un objeto de ViewNumber ( ViewGroup vg = new ViewNumber(this) ), es como inflar xml a continuación:

<ViewNumber I have no child :( </ViewNumber>

por lo tanto, si no sobrescribe en onLayout , ViewNumber''s onLayout no puede encontrar ningún elemento secundario, entonces estará en blanco.

@Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); }

después de anular, usará el método onLayout del padre de ViewNumber, si sus códigos son:

public class ViewNumber extends RelativeLayout { ... private void initView(Context context){ View.inflate(context, R.layout.shownumberlayout,this); } ... }

entonces es como inflar xml a continuación

<RelativeLayout <RelativeLayout your xml file /> </RelativeLayout>

hay un RelativeLayout más. Para escribir esto, puede escribir:

public class ViewNumber extends RelativeLayout { ... private void initView(Context context){ inflater.inflate( R.layout.login_view_layout, null ); //change (..,this) to (..,null) } ... }

Sin embargo, algo inesperado sucederá. android:layout_xxx=".." de su archivo xml puede cambiar (esta es la razón por la que su texto se coloca en la esquina superior izquierda). Para obtener más información y una mejor solución, puede ver la respuesta de talkol y el comentario de fgeorgiew debajo de ella :)