Diseños en las vistas

Prueba el método de Compose
Jetpack Compose es el kit de herramientas de IU recomendado para Android. Obtén información para trabajar con diseños en Compose.

Un diseño define la estructura de una interfaz de usuario en tu aplicación, como en un activity. Todos los elementos diseño se construyen mediante una jerarquía de View y ViewGroup objetos. Un View suele dibujar algo que el usuario puede ver y para interactuar. Un ViewGroup es un contenedor invisible que define la estructura de diseño de View y otros ViewGroup objetos, como se muestra en la figura 1.

Figura 1: Ilustración de una jerarquía de vistas, que define una Diseño de la IU

Los objetos View a menudo se denominan widgets y pueden ser uno de muchas subclases, como Button o TextView El Los objetos ViewGroup suelen llamarse diseños y pueden ser uno de ellos. de muchos tipos que proporcionan una estructura de diseño diferente, como LinearLayout o ConstraintLayout

Puedes declarar un diseño de dos maneras:

  • Declara elementos de la IU en XML. Android proporciona un archivo XML simple que corresponde a las clases y subclases View, como los de los widgets y diseños. También puedes usar las APIs de Android Studio Editor de diseño para compilar tu XML. con una interfaz de arrastrar y soltar.

  • Crea una instancia de elementos de diseño durante el tiempo de ejecución. Tu app puede crear Objetos View y ViewGroup, y manipulan sus propiedades de forma programática.

Declarar tu IU en XML te permite separar la presentación de tu app de el código que controla su comportamiento. El uso de archivos en formato XML también facilita la proporcionan diferentes diseños para diferentes tamaños y orientaciones de pantalla. Este es se analiza con más detalle en Cómo brindar compatibilidad con diferentes pantallas tamaños.

El framework de Android te brinda la flexibilidad de usar uno o ambos estos métodos para compilar la IU de tu app. Por ejemplo, puedes declarar el estado los diseños predeterminados en XML y, a continuación, modificar el diseño durante el tiempo de ejecución.

Escribe en XML

Con el vocabulario XML de Android, puedes crear rápidamente diseños de IU y de las los elementos de pantalla que contienen, de la misma manera en que se crean páginas web en HTML con una serie de elementos anidados.

Cada archivo de diseño debe contener exactamente un elemento raíz, que debe ser un Objeto View o ViewGroup. Después de definir la raíz puedes agregar widgets u objetos de diseño adicionales como elementos secundarios compila gradualmente una jerarquía View que defina tu diseño. Para Por ejemplo, aquí tienes un diseño XML que usa un LinearLayout vertical para Contiene una TextView y una Button:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:orientation="vertical" >
    <TextView android:id="@+id/text"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:text="Hello, I am a TextView" />
    <Button android:id="@+id/button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello, I am a Button" />
</LinearLayout>

Después de declarar tu diseño en XML, guarda el archivo con el .xml en el archivo res/layout/ de tu proyecto de Android para que se compile correctamente.

Para obtener más información sobre la sintaxis de un archivo en formato XML de diseño, consulta la sección Recurso de diseño.

Carga el recurso XML

Cuando compilas tu aplicación, cada archivo XML de diseño se compila en un recurso View. Carga el recurso de diseño en el archivo Activity.onCreate() implementación de devolución de llamada. Para ello, llama al setContentView(), y pasarle la referencia a tu recurso de diseño de la siguiente forma: R.layout.layout_file_name Por ejemplo, si tu archivo XML el diseño se guardó como main_layout.xml, cárgalo para tu Activity de la siguiente manera:

Kotlin

fun onCreate(savedInstanceState: Bundle) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main_layout)
}

Java

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main_layout);
}

El framework de Android llama al método de devolución de llamada onCreate() en tu Activity cuando se inicie Activity. Para ver más sobre los ciclos de vida de las actividades, consulta Introducción a actividades.

Atributos

Cada objeto View y ViewGroup admite su propio varios atributos XML. Algunos atributos son específicos de un View . Por ejemplo, TextView admite textSize. . Sin embargo, estos atributos también los hereda cualquier View. que extienden esta clase. Algunos son comunes a todos los View porque se heredan de la clase raíz View, como el atributo id. Otros atributos se consideran diseño parámetros, que son atributos que describen ciertas orientaciones de diseño del objeto View, según lo define el elemento superior ViewGroup.

ID

Cualquier objeto View puede tener un ID de número entero asociado a él para identifica de forma única el View dentro del árbol. Cuando la app esté se compila, se hace referencia a este ID como un número entero, pero se suele asignar en el archivo en formato XML de diseño como una cadena en el atributo id. Este es un Es un atributo XML común para todos los objetos View y está definido por el Clase View. Lo usas muy a menudo. La sintaxis para un ID dentro de un Una etiqueta XML es la siguiente:

android:id="@+id/my_button"

El símbolo at (@) al principio de la cadena indica que el analizador de XML analiza y expande el resto de la cadena de ID y la identifica como un recurso de ID. El símbolo más (+) significa que es un nuevo nombre de recurso. que debe crearse y agregarse a tus recursos en el R.java .

El framework de Android ofrece muchos otros recursos de ID. Cuando se hace referencia a un ID de recurso de Android, no necesitas el símbolo plus, pero debes agregar el Espacio de nombres del paquete android de la siguiente manera:

android:id="@android:id/empty"

El espacio de nombres del paquete android indica que haces referencia un ID de la clase de recursos android.R, en lugar del ID local resource.

Para crear vistas y hacer referencia a ellas desde tu app, puedes usar un de la siguiente manera:

  1. Define una vista en el archivo de diseño y asígnale un ID único, como en el siguiente ejemplo:
    <Button android:id="@+id/my_button"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/my_button_text"/>
    
  2. Crear una instancia del objeto View y capturarla desde el diseño normalmente, en la onCreate() como se muestra en el siguiente ejemplo:

    Kotlin

    val myButton: Button = findViewById(R.id.my_button)
    

    Java

    Button myButton = (Button) findViewById(R.id.my_button);
    

Definir IDs para objetos View es importante cuando se crea un RelativeLayout En un diseño relativo, las vistas del mismo nivel pueden definir su diseño en relación con otro del mismo nivel, a la que hace referencia el ID único.

No es necesario que un ID sea único en todo el árbol, pero únicos en la parte del árbol que buscas. A menudo, podría ser la totalidad de recursos, así que lo mejor es que sea único cuando sea posible.

Parámetros de diseño

Los atributos de diseño XML llamados layout_something definen parámetros de diseño de View que son adecuados para la ViewGroup en la que reside.

Cada clase ViewGroup implementa una clase anidada que extiende ViewGroup.LayoutParams Esta subclase contiene tipos de propiedad que definen el tamaño y la posición de cada secundaria, según corresponda para el grupo de vistas. Como se muestra en la figura 2, el elemento superior define los parámetros de diseño para cada vista secundaria, incluida la vista secundaria grupo de vistas.

Figura 2: Visualización de una jerarquía de vistas con diseño parámetros asociados con cada vista.

Cada subclase LayoutParams tiene su propia sintaxis para establecer de salida. Cada elemento secundario debe definir un LayoutParams que sea apropiado para su elemento superior, aunque también podría definir un LayoutParams para sus propios elementos secundarios.

Todos los grupos de vistas incluyen un ancho y una altura, con layout_width y layout_height, y se requiere que cada vista los defina. Muchos Las LayoutParams incluyen márgenes y bordes opcionales.

Puedes especificar el ancho y la altura con medidas exactas, pero es posible que no queremos hacerlo a menudo. La mayoría de las veces, se usa una de estas constantes para definir la ancho o alto:

  • wrap_content: Indica a tu vista que ajuste su tamaño en función del valor de dimensiones que requiere su contenido.
  • match_parent: Indica a tu vista que se agrande tanto como su elemento superior. que permite el grupo de vistas.

En general, no recomendamos especificar el ancho y la altura de un diseño con unidades absolutas, como los píxeles. Un mejor enfoque es usar mediciones relativas, como unidades de píxeles independientes de la densidad (dp), wrap_content o match_parent, ya que ayuda a que tu app se muestre correctamente en un varios tamaños de pantalla de dispositivos. Los tipos de medición aceptados se definen en Recurso de diseño.

Posición del diseño

Una vista tiene una geometría rectangular. Tiene una ubicación, expresada como un par de coordenadas izquierda y superior, y dos dimensiones, expresadas como ancho y alto. La unidad para la ubicación y las dimensiones es el píxel.

Puedes recuperar la ubicación de una vista invocando los métodos getLeft() y getTop() El primero muestra la coordenada izquierda (x) del rectángulo que representa la vista. El último devuelve la coordenada superior (y) del rectángulo que representan la vista. Estos métodos devuelven la ubicación de la vista en relación con a su elemento superior. Por ejemplo, cuando getLeft() muestra 20, significa que el valor está ubicada a 20 píxeles a la derecha del borde izquierdo de su superior.

Además, hay métodos convenientes para evitar cálculos innecesarios: es decir, getRight() y getBottom() Estos métodos devuelven las coordenadas de los bordes inferior y derecho de la rectángulo que representa la vista. Por ejemplo, llamar a getRight() es similar al siguiente cálculo: getLeft() + getWidth().

Tamaño, padding y márgenes

El tamaño de una vista se expresa en ancho y alto. Una vista tiene dos pares de los valores de ancho y alto.

El primer par se conoce como ancho medido, y altura medida. Estas dimensiones definen qué tan grande quiere ser una vista dentro de su elemento superior. Para obtener las dimensiones medidas, llama a getMeasuredWidth() y getMeasuredHeight()

El segundo par se conoce como ancho y altura, o a veces ancho de dibujo y alto de dibujo. Estas dimensiones definen la tamaño real de la vista en la pantalla, al momento de dibujar y después del diseño. Estos pueden diferir del ancho y la altura medidos, pero no necesariamente. Tú puedes obtener el ancho y la altura llamando getWidth() y getHeight()

Para medir estas dimensiones, una vista considera su relleno. El padding se expresa en píxeles para las partes izquierda, superior, derecha e inferior de la vista. Puedes usar padding para desplazar el contenido de la vista una determinada cantidad de píxeles. Por ejemplo, un relleno izquierdo de dos empuja el contenido de la vista dos píxeles. a la derecha del borde izquierdo. Puedes configurar el relleno con setPadding(int, int, int, int) y buscarlo llamando getPaddingLeft(), getPaddingTop(), getPaddingRight(), y getPaddingBottom()

Si bien una vista puede definir un relleno, no admite márgenes. Sin embargo, los grupos de vistas admiten márgenes. Consulta ViewGroup y ViewGroup.MarginLayoutParams para obtener más información.

Para obtener más información sobre las dimensiones, consulta Dimensión.

Además de configurar márgenes y padding de forma programática, también puedes establecerlos en tus diseños XML, como se muestra en el siguiente ejemplo:

  <?xml version="1.0" encoding="utf-8"?>
  <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:orientation="vertical" >
      <TextView android:id="@+id/text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_margin="16dp"
                android:padding="8dp"
                android:text="Hello, I am a TextView" />
      <Button android:id="@+id/button"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:layout_marginTop="16dp"
              android:paddingBottom="4dp"
              android:paddingEnd="8dp"
              android:paddingStart="8dp"
              android:paddingTop="4dp"
              android:text="Hello, I am a Button" />
  </LinearLayout>
  

En el ejemplo anterior, se muestra la aplicación del margen y el padding. El TextView tiene márgenes y padding uniformes aplicados en todas partes. Button muestra cómo puedes aplicarlos de forma independiente a diferentes en los bordes.

Diseños comunes

Cada subclase de la clase ViewGroup proporciona una forma única de mostrará las vistas que anidas en él. El tipo de diseño más flexible y el que que proporciona las mejores herramientas para que tu jerarquía de diseño sea superficial es ConstraintLayout

A continuación, se muestran algunos de los tipos de diseño comunes integrados en la biblioteca plataforma.

Cómo crear un diseño lineal

Organiza sus elementos secundarios en una sola fila horizontal o vertical, y crea una barra de desplazamiento si la longitud de la ventana supera la de la pantalla.

Cómo compilar apps web en WebView

Muestra páginas web.

Cómo crear listas dinámicas

Cuando el contenido de tu diseño sea dinámico o no sea predeterminado, puedes usar RecyclerView o una subclase de AdapterView RecyclerView suele ser la mejor opción, ya que usa memoria. con mayor eficiencia que AdapterView.

Diseños comunes posibles con RecyclerView y Las AdapterView incluyen lo siguiente:

Lista

Muestra una sola lista de columnas desplazable.

Cuadrícula

Muestra una cuadrícula desplazable de columnas y filas.

RecyclerView ofrece más posibilidades y la opción de crear una administrador de diseño.

Cómo rellenar una vista de adaptador con datos

Puedes propagar AdapterView como ListView o GridView el enlazando la instancia de AdapterView a una Adapter, que recupera datos de una fuente externa y crea un View que representa cada entrada de datos.

Android proporciona varias subclases de Adapter que son útiles para recuperar diferentes tipos de datos y crear vistas para una AdapterView Los dos adaptadores más comunes son los siguientes:

ArrayAdapter
Usa este adaptador cuando la fuente de datos sea un arreglo. De forma predeterminada, ArrayAdapter crea una vista para cada elemento del array llamando a toString() en cada elemento y colocar el contenido en un TextView.

Por ejemplo, si tienes un array de cadenas que quieres mostrar en un ListView, inicializa un nuevo ArrayAdapter con un para especificar el diseño de cada cadena y el array de cadenas:

Kotlin

    val adapter = ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, myStringArray)
    

Java

    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
            android.R.layout.simple_list_item_1, myStringArray);
    

Los argumentos para este constructor son los siguientes:

  • Tu app Context
  • El diseño que contiene una TextView para cada cadena de matriz
  • El arreglo de strings

Luego, llama setAdapter() en tu ListView:

Kotlin

    val listView: ListView = findViewById(R.id.listview)
    listView.adapter = adapter
    

Java

    ListView listView = (ListView) findViewById(R.id.listview);
    listView.setAdapter(adapter);
    

Para personalizar el aspecto de cada elemento, puedes anular el toString() para los objetos del array. O bien, para crear una vista para cada elemento que no es una TextView (por ejemplo, si quieres un elemento ImageView para cada elemento del array: extiende la clase ArrayAdapter y anular getView() para que devuelva el tipo de vista que deseas para cada elemento.

SimpleCursorAdapter
Usa este adaptador cuando tus datos provengan de un Cursor Cuando uses SimpleCursorAdapter, especifica el diseño que se usará para cada fila en el Cursor y qué columnas en el Cursor que desees insertar en las vistas del diseño que desees. Por ejemplo, si quieres crear una lista de nombres de personas y teléfonos números, puedes realizar una consulta que muestre un Cursor que contiene una fila para cada persona y columnas para los nombres y los números. Tú luego, crearé un array de cadenas que especifique qué columnas de la Cursor que desees en el diseño de cada resultado y un número entero que especifica las vistas correspondientes que cada columna debe colocado:

Kotlin

    val fromColumns = arrayOf(ContactsContract.Data.DISPLAY_NAME,
                              ContactsContract.CommonDataKinds.Phone.NUMBER)
    val toViews = intArrayOf(R.id.display_name, R.id.phone_number)
    

Java

    String[] fromColumns = {ContactsContract.Data.DISPLAY_NAME,
                            ContactsContract.CommonDataKinds.Phone.NUMBER};
    int[] toViews = {R.id.display_name, R.id.phone_number};
    

Cuando crees una instancia de SimpleCursorAdapter, pasa el diseño que se usará para cada resultado, el Cursor que contiene el resultados y estos dos arrays:

Kotlin

    val adapter = SimpleCursorAdapter(this,
            R.layout.person_name_and_number, cursor, fromColumns, toViews, 0)
    val listView = getListView()
    listView.adapter = adapter
    

Java

    SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
            R.layout.person_name_and_number, cursor, fromColumns, toViews, 0);
    ListView listView = getListView();
    listView.setAdapter(adapter);
    

Luego, SimpleCursorAdapter crea una vista para cada fila en el objeto Cursor con el diseño proporcionado insertando cada fromColumns elemento en el toViews correspondiente vista.

Si, en el transcurso del ciclo de vida de tu aplicación, cambias los datos subyacentes que lee tu adaptador, llama notifyDataSetChanged() Esto notifica a la vista adjunta que los datos se modificaron y se actualiza a sí mismo.

Cómo controlar eventos de clic

Puedes responder a eventos de clic en cada elemento de una AdapterView. implementando el AdapterView.OnItemClickListener interfaz de usuario. Por ejemplo:

Kotlin

listView.onItemClickListener = AdapterView.OnItemClickListener { parent, view, position, id ->
    // Do something in response to the click.
}

Java

// Create a message handling object as an anonymous class.
private OnItemClickListener messageClickedHandler = new OnItemClickListener() {
    public void onItemClick(AdapterView parent, View v, int position, long id) {
        // Do something in response to the click.
    }
};

listView.setOnItemClickListener(messageClickedHandler);

Recursos adicionales

Consulta cómo se usan los diseños en la Girasol app de demo en GitHub.