Разверните TextView с помощью wrap_content, пока вид соседа не достигнет конца родительского
Мне нужно выполнить следующий макет:
![enter image description here]()
У меня есть два TextViews в относительном макете: зеленый - это фиксированный текст с wrap_content
, черный имеет динамический текст с wrap_content
. Черный текст может измениться и стать очень длинным. Я хочу, чтобы черный TextView расширялся с текстом, пока зеленый вид не достигнет конца родителя. Если это произойдет, черный TextView должен прекратить расширять и эллипсировать конец.
Как я могу это достичь?
Что я пробовал:
<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>
Но когда черный текст становится все больше и больше, он выталкивает зеленый из вида
Ответы
Ответ 1
Вы можете архивировать этот макет с помощью атрибутов TableLayout
и 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>
![введите описание изображения здесь]()
Здесь - тот же вопрос;)
Ответ 2
Вот макет, который будет делать то, что вам нужно:
<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>
Ключевыми частями здесь являются гравитация относительной компоновки и выравнивание правильного текста как alignParentRight с левым текстовым окном, прикрепленным к левому.
Ответ 3
Я предлагаю обернуть два TextView
в LinearLayout
. Затем примените android:weightSum="1"
к этому LinearLayout
и примените android:layout_weight="1"
к дочернему элементу TextView
, который должен расширяться.
<?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>
Не забудьте установить два атрибута, чтобы он работал отлично:
android:ellipsize="end"
android:maxLines="1"
и LinearLayout
должны иметь android:layout_width="wrap_content"
Если вы хотите, чтобы этот ViewGroup
занимал все пространство, оберните его другим ViewGroup
:
<RelativeLayout
android:layout_height="wrap_content"
android:layout_width="match_parent">
<!--The previous view group-->
</RelativeLayout>
Ответ 4
Макет, который вы ожидаете, может быть создан с помощью layout_weight
attirbute, который поставляется с LinearLayout
. Таким образом, вам может понадобиться использовать LinearLayout
с weightSum
и layout_weight
(переходя к его атрибутам childview
).
Вот макет, который делит вашу ширину макета на четыре части, которая делится на 3: 1 между обоими Textview
. Непринужденное право Textview
, в результате чего left Textview
отображает текст как можно больше, он может отображаться без нарушения права Textview
.
Пожалуйста, не стесняйтесь попробовать с комбинацией вариантов weightSum
и layout_weight
в соответствии с вашими потребностями.
Разметка:
<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="StackOverflow StackOverflow StackOverflow "
/>
<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>
Ответ 5
Я устанавливаю максимальную ширину левой текстовой базы ширины правого текстового поля, просматриваю свой код. надеюсь, это поможет.
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();
}
а xml:
<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>
это скриншот после запуска:
![enter image description here]()
Ответ 6
В нашем приложении я столкнулся с таким видом использования. В нашем приложении есть 3 Просмотры. ImageView | TextView | ImageView
. Два изображения должны быть видны в макете. TextView должен быть эллипсирован в конце. И я придумал пользовательский ViewGroup
.
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);
}
}
Объявить пользовательский атрибут в значениях /attrs.xml
<declare-styleable name="PriorityLayoutHorizontal">
<attr name="priorityHigh" format="reference"/>
</declare-styleable>
Используя этот макет, вы можете придать высокий приоритет представлениям, которые должны быть видны в макете. Оставшийся один TextView будет нарисован на основе оставшейся ширины на экране.
Чтобы использовать этот макет:
<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>
И определите priority_array в значениях /arrays.xml
<integer-array name="priority_array">
<item>1</item>
</integer-array>
Здесь мы упоминали приоритет для представления "1". Это второй TextView в вашем макете. Таким образом, второй TextView будет виден всегда, а первый TextView будет эллипсирован.
P.S: это общее решение. т.е. это можно использовать с разными представлениями и более 2 представлений в строке. Вы можете использовать этот макет, или пользовательская ViewGroup, специфичная для вашей usecase, может быть написана.