android - layout_below - Expanda TextView con wrap_content hasta que la vista del vecino llegue al final del padre
relativelayout android studio (6)
Necesito lograr el siguiente diseño:
Tengo dos TextViews en un diseño relativo: el verde es texto fijo con wrap_content
, el negro tiene texto dinámico con wrap_content
. El texto negro puede cambiar y hacerse muy largo. Quiero que el TextView negro se expanda con el texto hasta que la vista verde llegue al final del padre. Si eso sucede, el TextView negro debería dejar de expandirse y cambiar de tamaño al final.
¿Cómo puedo lograr eso?
Lo que intenté:
<RelativeLayout
android:id="@+id/parent"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<TextView
android:id="@+id/leftTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:layout_alignParentLeft="true"
android:textSize="18sp" />
<TextView
android:id="@+id/rightTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/leftTextView"
android:textSize="18sp" />
</RelativeLayout>
Pero cuando el texto negro se hace más grande y más grande, empuja el verde fuera de la vista
Aquí hay un diseño que hará lo que le gustaría:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="left">
<TextView
android:id="@+id/leftTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLefOf="@+id/rightTextView"
android:maxLines="1"
android:textSize="18sp" />
<TextView
android:id="@+id/rightTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:textSize="18sp" />
</RelativeLayout>
Las partes clave aquí son la gravedad del diseño relativo y alinear la vista de texto derecha como alignParentRight con la vista de texto izquierda adjunta a la de la izquierda.
El diseño que se espera se puede crear con la ayuda de layout_weight
attirbute que viene con LinearLayout
. Por lo tanto, es posible que deba usar LinearLayout
con los weightSum
y layout_weight
(que pasan a su vista childview
).
Aquí hay un diseño que divide su ancho de diseño en cuatro partes que se divide en 3: 1 entre ambos Textview
. Al TextView
TextView a la derecha, TextView
izquierda muestra el texto lo más posible que puede mostrar sin perturbar a TextView a la derecha.
Por favor, siéntase libre de probar con la weightSum
variante de weightSum
y layout_weight
según su necesidad.
Diseño:
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="4" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:text=" "
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:layout_weight="3"
android:maxLines="1"
android:text="TextView"
android:textColor="@android:color/white" />
</LinearLayout>
Establecí el ancho máximo de la base de la vista de texto izquierda del ancho de la vista de texto derecha, eché un vistazo a mi código. Espero que esto ayude.
TextView leftText ;
TextView rightText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
leftText = (TextView) findViewById(R.id.leftTextView);
rightText = (TextView) findViewById(R.id.rightTextView);
measureView(leftText);
measureView(rightText);
leftText.setMaxWidth(getWidth() - rightText.getMeasuredWidth());
}
private void measureView(View view) {
ViewGroup.LayoutParams params = view.getLayoutParams();
int childWidth = ViewGroup.getChildMeasureSpec(0, view.getPaddingLeft() + view.getPaddingRight(), params.width);
int childHeight = ViewGroup.getChildMeasureSpec(0, view.getPaddingBottom() + view.getPaddingTop(), params.height);
view.measure(childWidth, childHeight);
}
private int getWidth() {
WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
return display.getWidth();
}
y el xml es:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/leftTextView"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:singleLine="true"
android:text="abadabadabadabadabadabadabadabadabadabaasdfasdfasdfadabadabadabadabadabadabadabadabadabadabaasdfasdfasdfadabadabadabadabadabadabadabadabadabadabaasdfasdfasdfad"/>
<TextView
android:id="@+id/rightTextView"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:textColor="#adc391"
android:singleLine="true"
android:text="adsfasd"/>
</LinearLayout>
Esta es la captura de pantalla después de ejecutar:
Le sugiero que TextView
dos TextView
en LinearLayout
. Luego aplique android:weightSum="1"
a este LinearLayout
y aplique android:layout_weight="1"
al TextView
secundario que debe extenderse.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:maxLines="1"
android:padding="8dp"
android:text="blabla bla bla bla bla bla bla bla bla bla bla bla bla "/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="8dp"
android:text="static text"/>
</LinearLayout>
Recuerda configurar los dos atributos para que funcione perfectamente:
android:ellipsize="end"
android:maxLines="1"
y LinearLayout
debe tener android:layout_width="wrap_content"
Si desea que este ViewGroup
tome todo el espacio, envuélvalo con otro ViewGroup
:
<RelativeLayout
android:layout_height="wrap_content"
android:layout_width="match_parent">
<!--The previous view group-->
</RelativeLayout>
Me he enfrentado a este tipo de caso en nuestra aplicación. En nuestra aplicación, hay 3 Vistas. ImageView | TextView | ImageView
ImageView | TextView | ImageView
. Las dos vistas de imagen deben estar visibles en el diseño. La vista de texto debe ser unlipsizada al final. Y se me ocurrió un ViewGroup
personalizado.
public class PriorityLayoutHorizontal extends ViewGroup
{
private ArrayList<Integer> mPriorityHighChildren;
public PriorityLayoutHorizontal(Context context)
{
this(context, null);
}
public PriorityLayoutHorizontal(Context context, AttributeSet attrs)
{
this(context, attrs, 0);
}
public PriorityLayoutHorizontal(Context context, AttributeSet attrs, int defStyleAttr)
{
super(context, attrs, defStyleAttr);
TypedArray typedArray = null;
try
{
typedArray = context.obtainStyledAttributes(attrs, R.styleable.PriorityLayoutHorizontal, defStyleAttr, 0);
final int id = typedArray.getResourceId(R.styleable.PriorityLayoutHorizontal_priorityHigh, -1);
if(id != -1)
{
final int[] highPriorityChildren = getResources().getIntArray(id);
setPriorityHigh(highPriorityChildren);
}
}
finally
{
if(typedArray != null)
{
typedArray.recycle();
}
}
}
public void setPriorityHigh(int... priorityHigh)
{
Integer[] priorityHighInteger = new Integer[priorityHigh.length];
int i = 0;
for(int value : priorityHigh)
{
priorityHighInteger[i++] = Integer.valueOf(value);
}
mPriorityHighChildren = new ArrayList<Integer>(Arrays.asList(priorityHighInteger));
}
int mMaxHeight = 0;
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthUsed = 0;
int heightUsed = 0;
final int childCount = getChildCount();
for(int childPosition : mPriorityHighChildren)
{
final View childView = getChildAt(childPosition);
if(childView.getVisibility() != View.GONE)
{
measureChildWithMargins(childView, widthMeasureSpec, widthUsed, heightMeasureSpec, heightUsed);
widthUsed += getMeasuredWidthWithMargins(childView);
heightUsed = Math.max(getMeasuredHeightWithMargins(childView), heightUsed);
}
}
for(int childPosition = 0; childPosition < childCount; childPosition++)
{
if(! mPriorityHighChildren.contains(Integer.valueOf(childPosition)))
{
final View childView = getChildAt(childPosition);
if(childView.getVisibility() != View.GONE)
{
measureChildWithMargins(childView, widthMeasureSpec, widthUsed, heightMeasureSpec, heightUsed);
widthUsed += getMeasuredWidthWithMargins(childView);
heightUsed = Math.max(getMeasuredHeightWithMargins(childView), heightUsed);
}
}
}
mMaxHeight = heightUsed;
int heightSize = heightUsed + getPaddingTop() + getPaddingBottom();
setMeasuredDimension(widthSize, heightSize);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
{
final int paddingLeft = getPaddingLeft();
final int paddingTop = getPaddingTop();
int spaceUsed = paddingLeft;
for (int childPosition = 0; childPosition < getChildCount(); childPosition++)
{
final View childView = getChildAt(childPosition);
if(childView.getVisibility() != View.GONE)
{
final int top = (mMaxHeight / 2) - (childView.getMeasuredHeight() / 2);
layoutView(childView, spaceUsed, paddingTop + top, childView.getMeasuredWidth(), childView.getMeasuredHeight());
spaceUsed += getWidthWithMargins(childView);
}
}
}
private int getWidthWithMargins(View child)
{
final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
return child.getWidth() + lp.leftMargin + lp.rightMargin;
}
private int getHeightWithMargins(View child)
{
final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
return child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
}
private int getMeasuredWidthWithMargins(View child)
{
final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
return child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
}
private int getMeasuredHeightWithMargins(View child)
{
final MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();
return child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
}
private void layoutView(View view, int left, int top, int width, int height)
{
MarginLayoutParams margins = (MarginLayoutParams) view.getLayoutParams();
final int leftWithMargins = left + margins.leftMargin;
final int topWithMargins = top + margins.topMargin;
view.layout(leftWithMargins, topWithMargins, leftWithMargins + width, topWithMargins + height);
}
@Override
public LayoutParams generateLayoutParams(AttributeSet attrs)
{
return new MarginLayoutParams(getContext(), attrs);
}
@Override
protected LayoutParams generateDefaultLayoutParams()
{
return new MarginLayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
}
}
Declare un atributo personalizado, en valores / attrs.xml
<declare-styleable name="PriorityLayoutHorizontal">
<attr name="priorityHigh" format="reference"/>
</declare-styleable>
Usando este diseño, puede dar alta prioridad a las Vistas que deberían estar visibles en el diseño definitivamente. El resto de un TextView se dibujará en función del ancho restante en la pantalla.
Para utilizar este diseño:
<com.example.component.PriorityLayoutHorizontal
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:priorityHigh="@array/priority_array"
>
<TextView
android:id="@+id/contact_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:singleLine="true"
/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/your_drawable"
/>
</com.example.component.PriorityLayoutHorizontal>
Y definir la matriz de prioridad en los valores / arrays.xml
<integer-array name="priority_array">
<item>1</item>
</integer-array>
Aquí, hemos mencionado la prioridad para la Vista "1". Ese es el segundo TextView en su diseño. Por lo tanto, la segunda vista de texto será visible siempre, y la primera vista de texto será ellipsada.
PD: esta es una solución genérica. es decir, esto se puede usar con diferentes Vistas y más de 2 Vistas en una línea. Puede usar este diseño, o podría escribirse un ViewGroup personalizado específico para su caso de uso.
Puede archivar este diseño mediante el atributo TableLayout
y shrinkColumns
.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Row 1 -->
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:shrinkColumns="0">
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="4dp"
android:maxLines="1"
android:ellipsize="end"
android:text="abcdefghijklmnopqrstuvwxyz"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="4dp"
android:maxLines="1"
android:ellipsize="none"
android:text="rightText"/>
</TableRow>
</TableLayout>
<!-- Row 2 -->
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:shrinkColumns="0">
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="4dp"
android:maxLines="1"
android:ellipsize="end"
android:text="Longer Text view abcdefghijklmnopqrstuvwxyz"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="4dp"
android:maxLines="1"
android:ellipsize="none"
android:text="rightText"/>
</TableRow>
</TableLayout>
<!-- Row 3 -->
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:shrinkColumns="0">
<TableRow
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="4dp"
android:maxLines="1"
android:ellipsize="end"
android:text="Text view that is very logn and will not fit the parent width abcdefghijklmnopqrstuvwxyz"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="4dp"
android:maxLines="1"
android:ellipsize="none"
android:text="rightText"/>
</TableRow>
</TableLayout>
</LinearLayout>
Here está la misma pregunta;)