Android: cómo escalar un diseño con tamaño de pantalla

Considere este diseño (sacado de aquí ):

Introduzca aquí la descripción de la imagen

Me gustaría entender los principios detrás de hacer esta escala de diseño con el tamaño de la pantalla. Para el cuadrado, una función onMeasure personalizada funciona muy bien:

@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, widthMeasureSpec); } 

El ancho y la altura de los botones Toggle y los botones de imagen personalizados a continuación deben escalarse para llenar el resto de la pantalla, menos layout_margins, y el texto y las imágenes dentro deben escalar para llenar los botones, menos padding. El margen externo también debe escalar.

Mi primer pensamiento fue usar un diseño relativo para colocar los botones y los atributos layout_margin / padding para crear márgenes. Sin embargo, los diseños relativos y layout_margin / padding requieren valores fijos de píxeles, por lo que no son escalables.

Luego pensé en usar diseños lineales anidados con layout_weights para colocar los botones y las vistas de marcador de posición para crear márgenes. Aunque estas técnicas son escalables, no funcionan con botones, porque los botones tienen muchos atributos (tamaño del texto, tamaño de la imagen, radio de la esquina, etc.) que requieren valores fijos de píxeles. Esta limitación significa, por ejemplo, que el siguiente xml:

 <ToggleButton android:layout_weight="1" style="@style/myButton" [...] /> <View android:layout_weight="1"/> <ImageButton android:layout_weight="1" style="@style/myButton" [...] /> 

No necesariamente hará que los dos botones, y el espacio entre ellos, tengan el mismo ancho. Todo depende del tamaño del texto, tamaño de la imagen, etc, etc de los botones.

He echado un vistazo a esta pregunta, pero siento que debería haber una solución más simple para un problema tan simple, que no debería requerir recurrir a demasiados no XML.

3 Solutions collect form web for “Android: cómo escalar un diseño con tamaño de pantalla”

Depende mucho del número de clases de View y ViewGroup que desee crear. Una implementación con el menor número de clases personalizadas que podría pensar sería algo como esto (muy similar a lo que ha descrito):

  • FrameLayout personalizado para el cuadrado más grande, con una implementación onMeasure() para que coincida con la altura al ancho disponible (ya mencionó éste).
  • Anidados LinearLayout instancias utilizando peso para obtener todos los botones de cuadrícula para ser del mismo tamaño.

El gran inconveniente de este enfoque es la eficiencia. Necesitará aproximadamente 36 instancias de LinearLayout para crear las pequeñas cuadrículas 9×9 dentro de una cuadrícula 9×9 mayor … que son 36 vistas de la sobrecarga de diseño puro.


En cuanto a tamaño de texto, hay un par de maneras que podría pensar en manejar esto. Uno sería utilizar Paint.measureTextBounds() (puede obtener el objeto Paint de cualquier TextView para realizar las mediciones) para determinar el tamaño que necesita para hacer el texto de cada botón después de haber sido medido. Desafortunadamente esto sería un proceso un tanto iterativo porque la Paint mide un texto dado basado en sus ajustes actuales, así que usted necesitaría:

  1. Establecer el tamaño del texto
  2. Medir límites
  3. Compruebe la altura
  4. Repita hasta que el tamaño sólo se ajuste

La buena noticia es que sólo tendría que hacer esto una vez y sólo se aplicará a todos los botones de la cuadrícula, pero tendría que esperar hasta que los botones de la cuadrícula se miden.

Otra opción aquí sería mostrar una imagen en lugar de texto dentro de algo como ImageView , que puede escalar el contenido para que su tamaño. Usted podría utilizar algo como TextDrawable que escribí para establecer el contenido de texto como una imagen que es escalable sin pérdida de calidad.


Ahora de vuelta al diseño. Usted podría ganar detrás una tonelada de eficacia creando un ViewGroup de la ViewGroup encargo para medir y poner hacia fuera la rejilla (el nombre GridLayout se toma ya … y no sirve absolutamente este propósito, así que llamémosle BlockLayout ). La creación de un BlockLayout personalizado le permitirá medir el tamaño de cada bloque y establecer 9 subviews en una cuadrícula con un solo padre en lugar de 4 instancias de LinearLayout . Ésta es básicamente la misma manera que usted mide el cuadrado total, apenas dividido uniformemente.

A continuación, podría construir todo el diseño con sólo 10 instancias de la sobrecarga de diseño … y aún menos si se puede codificar toda la cosa en un solo ViewGroup .

Básicamente, cuanto más código se pueda escribir para aplanar la jerarquía de vista, mejor será la aplicación en general.

HTH

Si usted construye sus vistas usando "dp" que, básicamente, ser el mismo tamaño para el tamaño de pantalla eack.
En la mayoría de los casos, preferirá que su vista se redimensione proporcionalmente al tamaño de la pantalla.
Por supuesto, en la mayoría de los casos necesitará construir diseños separados para tabletas.
Pero, además te puedo recomendar que realices los siguientes pasos:

1. Agregue esta biblioteca a su proyecto.

2. Ahora en su diseño puede escribir vistas como esta:

 <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="I'm scalable!" android:textSize="@dimen/_12sdp"/> 

En este ejemplo, su TextView se escalará en cada tamaño de pantalla.

3. Haga una vista previa de todos los tamaños de pantalla para ver el resultado.

Para complementar la respuesta de Devnuwired, puede escribir un método similar a esto para agregar su texto TextDrawable a un ImageButton :

 private void addText(String text, ImageButton button, int colour) { TextDrawable d = new TextDrawable(this); d.setText(text); d.setTextColor(colour); d.setTextAlign(Layout.Alignment.ALIGN_CENTER); button.setImageDrawable(d); } 

O alternativamente

 private void addText(String text, int buttonID, int colour) { TextDrawable d = new TextDrawable(this); d.setText(text); d.setTextColor(colour); d.setTextAlign(Layout.Alignment.ALIGN_CENTER); ((ImageButton) findViewById(buttonID)).setImageDrawable(d); } 
  • Android expandablelistview cómo establecer el espacio entre los elementos de los grupos
  • Diferencia entre? SelectableItemBackground,? Android: selectableItemBackground y? Android: attr / selectableItemBackground en Android?
  • GetActivity (). FindViewById devuelve null, llamado desde el fragmento onActivityCreated
  • Añadir una imagen de fondo a la forma en XML Android
  • Android BitmapDrawable setTileModeX no funciona en TextView
  • XML predeterminado para la notificación de estado
  • Atributo desconocido androide: elevación
  • SelectableItemBackground como elemento en la lista de capas
  • Android por qué este botón no se puede hacer clic
  • Cambiar el color del icono xml drawable
  • Android Studio: xmlns: el mapa no funciona
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.