Reputation: 1630
I am trying to achieve the following layout:
+----------------------------------------+
| [icon] [text] [icon] |
+----------------------------------------+
| [icon] [very loooooooooooooooooo [icon]|
| oooooooooooooooong text] |
+----------------------------------------+
When the text is short, the icon on the right needs to be right next to the text (not right aligned). When the text is long, I need the text to be wrapped.
I have tried to use LinearLayout and RelativeLayout, but the icons are still got pushed out when I have a long text. Here are the layouts I have tried:
LinearLayout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="left"/>
<TextView
android:id="@+id/middle"
android:text="a long long string, a long long string, a long long string, a long long string, a long long string, a long long string, "
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#D0E198"/>
<TextView
android:id="@+id/right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="right"/>
</LinearLayout>
RelativeLayout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="left"/>
<TextView
android:id="@+id/middle"
android:text="a long long string, a long long string, a long long string, a long long string, a long long string, a long long string, "
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#D0E198"
android:layout_toRightOf="@id/left"/>
<TextView
android:id="@+id/right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="right"
android:layout_toRightOf="@id/middle"/>
</RelativeLayout>
In both cases, the right icon is pushed out of the screen.
I have also tried LinearLayout with layout_weight="1" on the left and right view and 0 on the middle view. That pushes both icons off screen.
Upvotes: 13
Views: 6153
Reputation: 648
I know this is a late answer on this thread, but I found the solution and would like to share it with others.
To fix this you should be using ConstraintLayout:
<androidx.constraintlayout.widget.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">
<ImageView
android:id="@+id/iconStart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/unread_circuler_dot"
app:layout_constraintEnd_toStartOf="@id/text"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
android:text="Very long text"
android:textColor="@color/white"
app:layout_constraintEnd_toStartOf="@id/iconEnd"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="@id/iconStart"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_default="wrap" />
<ImageView
android:id="@+id/iconEnd"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/unread_circuler_dot"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toEndOf="@id/text"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
The key to this fix is the line app:layout_constraintWidth_default="wrap"
Information about this from Google themselves:
Wrap: Expands the view only as much as needed to fit its contents, but still allows the view to be smaller than that if the constraints require it. So the difference between this and using Wrap Content (above), is that setting the width to Wrap Content forces the width to always exactly match the content width; whereas using Match Constraints with layout_constraintWidth_default set to wrap also allows the view to be smaller than the content width.
More information can be found here
Update!!
Since app:layout_constraintWidth_default="wrap"
has been deprecated, the main way to achieve the same effect is by using it with
android:layout_width="wrap_content"
app:layout_constrainedWidth="true"
Upvotes: 8
Reputation: 56
You should set the second view's android:layout_weight
to a value less than 1, so that it keeps expanding until the last view reaches the tip of the layout.
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="@+id/right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="right"/>
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:maxLines="1"
android:ellipsize="end"/>
<TextView
android:id="@+id/left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="left"/>
</LinearLayout>
Upvotes: 0
Reputation: 391
After some hair pulling and no obvious sollution I came to this hack. The custom textview class only works for textviews and I needed it to work for a layout with multiple things. Limitation of this is that you have to have the max width defined for the right element. This does remind me a bit of the old html IE 6 days..
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<FrameLayout
android:id="@+id/resizing_element"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="112dp" // Right padding to the amount of space you need for the right element
android:background="@drawable/bg_chat_in" // Background drawable has the same transparant padding added to complete the illusion of this hack
android:text="Long text content" />
<FrameLayout
android:id="@+id/meta_container"
android:layout_width="112db" // This one has to have a predefined size.
android:layout_height="wrap_content"
android:layout_alignRight="@+id/content_container" // Align right places this element in the right padding of the first element>
</FrameLayout>
</RelativeLayout>
Upvotes: 0
Reputation: 304
You can reference this; First you layout the first left Icon, then use the reference method to layout [text view and right icon];
It works absolutely!
Of course, According to your requirement, the last right icon can set as the middle textview DrawableRight. But this method has one constraint: the the right icon bound limits to textview bound.
Upvotes: -1
Reputation: 1630
Here is what I have done to achieve what I want:
I added layout_weight="1" to the middle TextView
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="left"/>
<WrapWidthTextView
android:id="@+id/middle"
android:text="a long long string, a long long string, a long long string, a long long string, a long long string, a long long string, "
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#D0E198"
android:layout_weight="1"/>
<TextView
android:id="@+id/right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="right"/>
</LinearLayout>
However, when the middle text is short, it will still occupy the entire empty middle space and pushes the right TextView all the way to the right. I have to subclass TextView:
public class WrapWidthTextView
extends TextView {
// constructors here
@Override protected void onMeasure (final int widthMeasureSpec, final int heightMeasureSpec) {
super.onMeasure (widthMeasureSpec, heightMeasureSpec);
Layout layout = getLayout ();
if (layout != null) {
int width = (int) Math.ceil (getMaxLineWidth (layout))
+ getCompoundPaddingLeft () + getCompoundPaddingRight ();
int height = getMeasuredHeight ();
setMeasuredDimension (width, height);
}
}
private float getMaxLineWidth (Layout layout) {
float max_width = 0.0f;
int lines = layout.getLineCount ();
for (int i = 0; i < lines; i++) {
if (layout.getLineWidth (i) > max_width) {
max_width = layout.getLineWidth (i);
}
}
return max_width;
}
}
With WrapWidthTextView, when the text is short, it will shrink the view to fit the text.
And that solved my problem. I hope this will help others as well.
Upvotes: 6
Reputation: 891
you can check :
(middle :
android:layout_toLeftOf="@+id/right"
android:layout_toRightOf="@+id/left"
)
(right :android:layout_alignParentRight="true"
)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="left"/>
<TextView
android:id="@+id/middle"
android:text=" a long long string, a long long string, a long long string, a long long string, a long long string, a long long string, "
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#D0E198"
android:layout_centerInParent="true"
android:layout_toLeftOf="@+id/right"
android:layout_toRightOf="@+id/left"/>
<TextView
android:id="@+id/right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="right"
android:layout_alignParentRight="true"
/>
</RelativeLayout>
Upvotes: 0
Reputation: 93561
Set a maxWidth to the text field. It won't get bigger than that. You can also set maxLines to stop wrapping to a new line.
Upvotes: 2
Reputation: 5551
Use the first layout, but add weighting to your middle textview.
Example:
<TextView
android:id="@+id/middle"
android:text="a long long string, a long long string, a long long string, a long long string, a long long string, a long long string, "
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:background="#D0E198"/>
Make sure to use 0dp as your width!
Note: This answer is if you want the icon to be right aligned. Which, I'm not sure that's what you need.
Upvotes: 3