android - linearlayout - Porcentaje de ancho en un RelativeLayout
relativelayout android studio español (14)
Estoy trabajando en un diseño de formulario para una Activity
inicio de sesión en mi aplicación de Android. La imagen de abajo es como quiero que se vea:
Pude lograr este diseño con el siguiente XML . El problema es que es un poco pirateado. Tuve que codificar el ancho del host EditText. Específicamente, tuve que especificar:
android:layout_width="172dp"
Realmente me gustaría dar un porcentaje de ancho al host y al puerto EditText. (Algo así como 80% para el host, 20% para el puerto). ¿Es esto posible? El siguiente XML funciona en mi Droid, pero no parece funcionar para todas las pantallas. Realmente me gustaría una solución más robusta.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/main"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:id="@+id/host_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/home"
android:paddingLeft="15dp"
android:paddingTop="0dp"
android:text="host"
android:textColor="#a5d4e2"
android:textSize="25sp"
android:textStyle="normal" />
<TextView
android:id="@+id/port_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/home"
android:layout_toRightOf="@+id/host_input"
android:paddingTop="0dp"
android:text="port"
android:textColor="#a5d4e2"
android:textSize="25sp"
android:textStyle="normal" />
<EditText
android:id="@+id/host_input"
android:layout_width="172dp"
android:layout_height="wrap_content"
android:layout_below="@id/host_label"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="4dp"
android:background="@android:drawable/editbox_background"
android:inputType="textEmailAddress" />
<EditText
android:id="@+id/port_input"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_below="@id/host_label"
android:layout_marginTop="4dp"
android:layout_toRightOf="@id/host_input"
android:background="@android:drawable/editbox_background"
android:inputType="number" />
<TextView
android:id="@+id/username_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/host_input"
android:paddingLeft="15dp"
android:paddingTop="15dp"
android:text="username"
android:textColor="#a5d4e2"
android:textSize="25sp"
android:textStyle="normal" />
<EditText
android:id="@+id/username_input"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/username_label"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="4dp"
android:background="@android:drawable/editbox_background"
android:inputType="textEmailAddress" />
<TextView
android:id="@+id/password_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/username_input"
android:paddingLeft="15dp"
android:paddingTop="15dp"
android:text="password"
android:textColor="#a5d4e2"
android:textSize="25sp"
android:textStyle="normal" />
<EditText
android:id="@+id/password_input"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="@id/password_label"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:layout_marginTop="4dp"
android:background="@android:drawable/editbox_background"
android:inputType="textPassword" />
<ImageView
android:id="@+id/home"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_centerVertical="false"
android:paddingLeft="15dp"
android:paddingRight="15dp"
android:paddingTop="15dp"
android:scaleType="fitStart"
android:src="@drawable/home" />
<Button
android:id="@+id/login_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/password_input"
android:layout_marginLeft="15dp"
android:layout_marginTop="15dp"
android:text=" login "
android:textSize="18sp" >
</Button>
</RelativeLayout>
Actualización 1
Como señala @EmJiHash PercentRelativeLayout está en desuso en el nivel de API 26.0.0
Abajo citando el comentario de google:
Esta clase fue desaprobada en el nivel de API 26.0.0. considere usar ConstraintLayout y diseños asociados en su lugar. A continuación se muestra cómo replicar la funcionalidad de diseños de porcentaje con un ConstraintLayout
Google introdujo una nueva API llamada android.support.percent
Entonces solo puede especificar el porcentaje para tomar por vista
Añadir compilar dependencia como
compile ''com.android.support:percent:22.2.0
en eso, PercentRelativeLayout es lo que podemos hacer un diseño de porcentaje
<android.support.percent.PercentRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
app:layout_widthPercent="50%"
app:layout_heightPercent="50%"
app:layout_marginTopPercent="25%"
app:layout_marginLeftPercent="25%"/>
</android.support.percent.PercentRelativeLayout>
Consulte https://github.com/mmin18/FlexLayout que puede usar el porcentaje o la expresión java directamente en el diseño XML.
<EditText
app:layout_left="0%"
app:layout_right="60%"
app:layout_height="wrap_content"/>
<EditText
app:layout_left="prev.right+10dp"
app:layout_right="100%"
app:layout_height="wrap_content"/>
Curiosamente, basándose en la respuesta de @olefevre, uno no solo puede hacer diseños 50/50 con "puntales invisibles", sino todo tipo de diseños que involucran poderes de dos.
Por ejemplo, aquí hay un diseño que corta el ancho en cuatro partes iguales (en realidad tres, con pesos de 1, 1, 2):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<View
android:id="@+id/strut"
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_centerHorizontal="true"
android:background="#000000" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="@+id/strut" >
<View
android:id="@+id/left_strut"
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_toLeftOf="@+id/strut"
android:layout_centerHorizontal="true"
android:background="#000000" />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignRight="@+id/left_strut"
android:text="Far Left" />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_toRightOf="@+id/left_strut"
android:text="Near Left" />
</RelativeLayout>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/strut"
android:layout_alignParentRight="true"
android:text="Right" />
</RelativeLayout>
Debido a que PercentRelativeLayout quedó en desuso en 26.0.0 y los diseños anidados como LinearLayout dentro de RelativeLayout tienen un impacto negativo en el rendimiento ( Entendiendo los beneficios de rendimiento de ConstraintLayout ), la mejor opción para que usted logre un porcentaje de ancho es reemplazar su RelativeLayout con ConstraintLayout.
Esto se puede resolver de dos maneras.
SOLUCIÓN # 1 Usando pautas con porcentaje de desplazamiento
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/host_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Host"
android:layout_marginTop="16dp"
android:layout_marginLeft="8dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="@+id/host_input" />
<TextView
android:id="@+id/port_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Port"
android:layout_marginTop="16dp"
android:layout_marginLeft="8dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="@+id/port_input" />
<EditText
android:id="@+id/host_input"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:inputType="textEmailAddress"
app:layout_constraintTop_toBottomOf="@+id/host_label"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/guideline" />
<EditText
android:id="@+id/port_input"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:inputType="number"
app:layout_constraintTop_toBottomOf="@+id/port_label"
app:layout_constraintLeft_toLeftOf="@+id/guideline"
app:layout_constraintRight_toRightOf="parent" />
<android.support.constraint.Guideline
android:id="@+id/guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.8" />
</android.support.constraint.ConstraintLayout>
SOLUCIÓN # 2 Usando cadena con ancho ponderado para EditText
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/host_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Host"
android:layout_marginTop="16dp"
android:layout_marginLeft="8dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="@+id/host_input" />
<TextView
android:id="@+id/port_label"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Port"
android:layout_marginTop="16dp"
android:layout_marginLeft="8dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="@+id/port_input" />
<EditText
android:id="@+id/host_input"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:inputType="textEmailAddress"
app:layout_constraintHorizontal_weight="0.8"
app:layout_constraintTop_toBottomOf="@+id/host_label"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/port_input" />
<EditText
android:id="@+id/port_input"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:inputType="number"
app:layout_constraintHorizontal_weight="0.2"
app:layout_constraintTop_toBottomOf="@+id/port_label"
app:layout_constraintLeft_toRightOf="@+id/host_input"
app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>
En ambos casos, obtienes algo como esto.
Esto no responde completamente a la pregunta original, que era para una división 70/30, pero en el caso especial de una división 50/50 entre los componentes hay una manera: coloque un puntal invisible en el centro y utilícelo para colocar el Dos componentes de interés.
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<View android:id="@+id/strut"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_centerHorizontal="true"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignRight="@id/strut"
android:layout_alignParentLeft="true"
android:text="Left"/>
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/strut"
android:layout_alignParentRight="true"
android:text="Right"/>
</RelativeLayout>
Como este es un caso bastante común, esta solución es más que una curiosidad. Es un poco difícil pero eficiente porque el puntal vacío de tamaño cero debería costar muy poco.
En general, sin embargo, es mejor no esperar demasiado de los diseños comunes de Android ...
He resuelto esto creando una vista personalizada:
public class FractionalSizeView extends View {
public FractionalSizeView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public FractionalSizeView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = MeasureSpec.getSize(widthMeasureSpec);
setMeasuredDimension(width * 70 / 100, 0);
}
}
Este es un puntal invisible que puedo usar para alinear otras vistas dentro de RelativeLayout.
No puede usar porcentajes para definir las dimensiones de una Vista dentro de un RelativeLayout. La mejor manera de hacerlo es usar LinearLayout y los pesos, o un diseño personalizado.
Puede usar PercentRelativeLayout , es una adición reciente e indocumentada a la Biblioteca de Soporte de Diseño , permite la capacidad de especificar no solo los elementos relacionados entre sí, sino también el porcentaje total de espacio disponible.
Subclase de RelativeLayout que admite dimensiones y márgenes basados en porcentajes. Puede especificar una dimensión o un margen de hijo usando atributos con el sufijo "Porcentaje".
<android.support.percent.PercentRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_widthPercent="50%"
app:layout_heightPercent="50%"
app:layout_marginTopPercent="25%"
app:layout_marginLeftPercent="25%"/>
</android.support.percent.PercentFrameLayout>
El paquete Porcentaje proporciona API para admitir agregar y administrar dimensiones basadas en porcentajes en su aplicación.
Para usarlo, debe agregar esta biblioteca a su lista de dependencias de Gradle :
dependencies {
compile ''com.android.support:percent:22.2.0''//23.1.1
}
Puedes echar un vistazo a la nueva biblioteca de porcentajes de soporte.
compile ''com.android.support:percent:22.2.0''
Simplemente coloque sus dos vistas de texto, el host y el puerto en una configuración lineal independiente horizontal y use android: layout_weight para hacer el porcentaje
Usted está buscando el atributo android:layout_weight
. Te permitirá usar porcentajes para definir tu diseño.
En el siguiente ejemplo, el botón izquierdo utiliza el 70% del espacio y el botón derecho el 30%.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:text="left"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".70" />
<Button
android:text="right"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight=".30" />
</LinearLayout>
Funciona de la misma manera con cualquier tipo de Vista, puede reemplazar los botones con algún Texto de Edición para que se ajuste a sus necesidades.
Asegúrese de establecer layout_width
en 0dp
o sus vistas no se escalarán correctamente.
Tenga en cuenta que la suma de pesos no tiene que ser igual a 1, me parece más fácil leer así. Puede establecer el primer peso en 7 y el segundo en 3 y dará el mismo resultado.
Usted puede lograr esto a través de pesos de diseño. Un peso determina cómo se dividen las partes no reclamadas de la pantalla. Dé a cada EditText un layout_width de 0 y un peso proporcional. Es decir, dale a uno un peso de 2, y el otro un peso de 1 si quieres que el primero ocupe el doble de espacio.
PercentRelativeLayout está en desuso desde la versión 26.0.0 de la biblioteca de soporte.
Google introdujo un nuevo diseño llamado ConstraintLayout .
Agregue la biblioteca como una dependencia en su archivo build.gradle a nivel de módulo:
dependencies {
compile ''com.android.support.constraint:constraint-layout:1.0.1''
}
solo agregue en un archivo de diseño:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.constraint.ConstraintLayout>
Restricciones
Las restricciones te ayudan a mantener los widgets alineados. Puede usar anclajes, como los controles de restricción que se muestran a continuación, para determinar las reglas de alineación entre varios widgets.
-
Wrap Content
: la vista se expande según sea necesario para ajustarse a su contenido. -
Match Constraints
: la vista se expande según sea necesario para cumplir con la definición de sus restricciones después de tener en cuenta los márgenes. Sin embargo, si la dimensión dada tiene solo una restricción, entonces la vista se expande para ajustarse a su contenido. El uso de este modo en la altura o en el ancho también le permite establecer una relación de tamaño. -
Fixed
: especifica una dimensión específica en el cuadro de texto debajo o cambiando el tamaño de la vista en el editor. -
Spread
: las vistas se distribuyen uniformemente (una vez que se tienen en cuenta los márgenes). Este es el valor predeterminado. -
Spread inside
: la primera y la última vista se fijan a las restricciones en cada extremo de la cadena y el resto se distribuye uniformemente. -
Weighted
: cuando la cadena está configurada para extenderse o extenderse adentro, puedes llenar el espacio restante configurando una o más vistas para "coincidir restricciones" (0dp). De forma predeterminada, el espacio se distribuye uniformemente entre cada vista que se establece en "restricciones de coincidencia", pero puede asignar un peso de importancia a cada vista utilizando los atributos layout_constraintHorizontal_weight y layout_constraintVertical_weight. Si está familiarizado con layout_weight en un diseño lineal, esto funciona de la misma manera. Así que la vista con el valor de mayor peso obtiene la mayor cantidad de espacio; Las vistas que tienen el mismo peso obtienen la misma cantidad de espacio. -
Packed
: las vistas se empaquetan juntas (después de que se contabilizan los márgenes). Luego puede ajustar el sesgo de toda la cadena (izquierda / derecha o arriba / abajo) cambiando el sesgo de la vista de la cabeza de la cadena. -
Center Horizontally or Center Vertically
: para crear una cadena de vistas rápidamente, selecciónelas todas, haga clic con el botón derecho en una de las vistas y luego seleccione Centrar horizontalmente o Centrar verticalmente, para crear una cadena horizontal o vertical -
Baseline alignment
: Alinee la línea de base de texto de una vista con la línea de base de texto de otra vista. -
Constrain to a guideline
: puede agregar una directriz vertical u horizontal a la que puede restringir las vistas, y la directriz será invisible para los usuarios de la aplicación. Puede colocar la guía dentro del diseño según las unidades dp o el porcentaje, en relación con el borde del diseño. -
Adjust the constraint bias
: cuando agrega una restricción a ambos lados de una vista (y el tamaño de vista para la misma dimensión es "fijo" o "ajuste de contenido"), la vista se centra entre las dos restricciones con un sesgo de 50 % por defecto. Puede ajustar el sesgo arrastrando el control deslizante de sesgo en la ventana Propiedades -
Set size as a ratio
: puede establecer el tamaño de la vista en una proporción como 16: 9 si al menos una de las dimensiones de la vista se establece en "restricciones de coincidencia" (0dp).
Puedes aprender más del doc oficial.
Actualizar
Como señala @EmJiHash, PercentRelativeLayout y PercentFrameLayout están en desuso en el nivel de API 26.0.0
Considere usar ConstraintLayout
Google introdujo una nueva API llamada android.support.percent
1) PercentRelativeLayout
2) PercentFrameLayout
Añadir compilar dependencia como
compile ''com.android.support:percent:23.1.1''
Puede especificar la dimensión en porcentaje, así que obtenga tanto el beneficio de RelativeLayout
como el porcentaje
<android.support.percent.PercentRelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView
app:layout_widthPercent="40%"
app:layout_heightPercent="40%"
app:layout_marginTopPercent="15%"
app:layout_marginLeftPercent="15%"/>
</android.support.percent.PercentRelativeLayout/>