Two TextViews side by side, only one to ellipsize? - android

I want to have two TextView elements appear side by side (in a list item), one aligned to the left, one to the right. Something like:
|<TextView> <TextView>|
(the | represent the screen's extremities)
However, the TextView on the left can have content that is too long to fit on the screen. In this case, I want to have it ellipsize but still show the entire right TextView. Something like:
|This is a lot of conte...<TextView>|
I have had numerous attempts at this, using both LinearLayout and RelativeLayout, and the only solution I have come up with is to use a RelativeLayout and put a marginRight on the left TextView big enough to clear the right TextView. As you can imagine, though, this is not optimal.
Are there any other solutions?
Final, LinearLayout solution:
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:orientation="horizontal"
>
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_weight="1"
android:ellipsize="end"
android:inputType="text"
/>
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_weight="0"
android:layout_gravity="right"
android:inputType="text"
/>
</LinearLayout>
Old, TableLayout solution:
<TableLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:stretchColumns="1"
android:shrinkColumns="0"
>
<TableRow>
<TextView android:id="#+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:singleLine="true"
/>
<TextView android:id="#+id/date"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:singleLine="true"
android:ellipsize="none"
android:gravity="right"
/>
</TableRow>
</TableLayout>

Just an idea, why don't you declare first in the xml layout the textview on the right and set its width as wrap content, android:layout_alignParentRight="true" and android:gravity="right". Then declare the textview on the left, set its width as fill parent, android:layout__toLeftOf={the id of the textview on the right} having RelativeView as the root view.
By declaring first the right textview, its required width will be computed first and occupy the view while the textview on the left will occupy the remaining space of the view.
I still have not tried this though it might give you some idea.
[Update]
I tried creating an xml resource layout... and it somehow works...
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:id="#+id/right"
android:layout_alignParentRight="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="right"
android:text="right"
>
</TextView>
<TextView
android:id="#+id/left"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="#id/right"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:lines="1"
android:singleLine="true"
android:maxLines="1"
android:text="too looooooooooong ofskgjo sdogj sdkogjdfgds dskjgdsko jgleft"
>
</TextView>
</RelativeLayout>

The LinearLayout answer worked for me with this same problem. Posted as a separate answer because it wasn't clear what did and didn't work for the asker.
One difference. TableLayout was less ideal for me because I had two rows of data, and I wanted the bottom row to behave as this question describes, and the top row to span the area. That question's been answered in another SO question: Colspan in TableLayout, but LinearLayout was simpler.
Though getting the widths right took me a bit. I included the android lint tweak of using 0dp width on the scaling item for performance.
<LinearLayout
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:orientation="horizontal"
>
<TextView
android:layout_height="wrap_content"
android:layout_width="0dp"
android:layout_weight="1"
android:ellipsize="end"
android:inputType="text"
/>
<TextView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_weight="0"
android:layout_gravity="right"
android:inputType="text"
/>
</LinearLayout>

Use TableLayout and put both TextView in table row, have a try. I haven't tried

There are many answers to this and practically equivalent, duplicate questions on SO. The suggested approaches usually work, sort of. Putting it into a LinearLayout, wrap the whole in an extra RelativeLayout, use a TableLayout; all these seem to solve it for a simpler layout but if you need these two TextViews inside something more complicated, or the same layout will be reused, for instance, by a RecyclerView, things get broken very quickly.
The only solution I found that really works all the time, regardless of what bigger layout you put it into, is a custom layout. It's very simple to implement, and being as lean as it possibly gets, it will keep the layout reasonably flat, it's easy to maintain—so in the long run, I consider this the best solution to the problem.
public class TwoTextLayout extends ViewGroup {
public TwoTextLayout(Context context) {
super(context);
}
public TwoTextLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public TwoTextLayout(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int count = getChildCount();
if (count != 2)
throw new IllegalStateException("TwoTextLayout needs exactly two children");
int childLeft = this.getPaddingLeft();
int childTop = this.getPaddingTop();
int childRight = this.getMeasuredWidth() - this.getPaddingRight();
int childBottom = this.getMeasuredHeight() - this.getPaddingBottom();
int childWidth = childRight - childLeft;
int childHeight = childBottom - childTop;
View text1View = getChildAt(0);
text1View.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.AT_MOST));
int text1Width = text1View.getMeasuredWidth();
int text1Height = text1View.getMeasuredHeight();
View text2View = getChildAt(1);
text2View.measure(MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.AT_MOST), MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.AT_MOST));
int text2Width = text2View.getMeasuredWidth();
int text2Height = text2View.getMeasuredHeight();
if (text1Width + text2Width > childRight)
text1Width = childRight - text2Width;
text1View.layout(childLeft, childTop, childLeft + text1Width, childTop + text1Height);
text2View.layout(childLeft + text1Width, childTop, childLeft + text1Width + text2Width, childTop + text2Height);
}
}
The implementation couldn't be simpler, it just measures the two texts (or any other child views, actually) and if their combined width exceeds the layout width, reduces the width of the first view.
And if you need modifications, eg. to align the second text to the baseline of the first, you can solve that easily, too:
text2View.layout(childLeft + text1Width, childTop + text1Height - text2Height, childLeft + text1Width + text2Width, childTop + text1Height);
Or any other solution, like shrinking the second view in relation to the first, aligning to the right, etc.

Why don't you put a left margin on the right TextView? I'm using this approach for a
|<TextView> <ImageButton>|
and it works.

Solution with ConstraintLayout
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="8dp">
<TextView
android:id="#+id/leftText"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
app:layout_constraintEnd_toStartOf="#id/rightText"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="This is a lot of content that should be cut" />
<TextView
android:id="#+id/rightText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Right text" />
</androidx.constraintlayout.widget.ConstraintLayout>

When I faced with the sililar issue, I did following:
I needed:
|<TextView, may be long> <TextViewFixedSize> |
|<TextView, may be longer ...> <TextViewFixedSize>|
|<TextViewLong> <TextViewFixedSize> |
You may use a solution like this:
<androidx.constraintlayout.widget.ConstraintLayout
android:id="#+id/layoutRecommendedServiceDescription"
android:layout_width="0dp"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="#+id/textViewRecommendedServiceTitle"
app:layout_constraintTop_toBottomOf="#id/textViewRecommendedServiceTitle">
<TextView
android:id="#+id/textViewRecommendedService1"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:ellipsize="end"
android:lines="1"
android:maxLines="1"
app:layout_constrainedWidth="true"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintEnd_toStartOf="#+id/textViewRecommendedServicePopular"
app:layout_constraintStart_toStartOf="parent"
tools:text="Long text"
tools:visibility="visible" />
<TextView
android:id="#+id/textViewRecommendedServicePopular"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginStart="8dp"
android:lines="1"
android:text="#string/services_popular"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/textViewRecommendedService1"
app:layout_goneMarginStart="0dp"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>

Related

Getting measured height in Android Studio doesn't work properly

I have multiple list views inside a scrollable view, so I used a function that computes the height of a list view and sets it so the list view is not scrollable anymore.
public static void setHeightListView(ListView listView) {
Adapter adapter = listView.getAdapter();
int UNBOUNDED = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
int height = listView.getDividerHeight() * (listView.getCount() - 1);
for (int i = 0; i < adapter.getCount(); ++i) {
View child = adapter.getView(i, null, listView);
child.measure(UNBOUNDED, UNBOUNDED);
height += child.getMeasuredHeight();
}
ViewGroup.LayoutParams listViewParams = listView.getLayoutParams();
listViewParams.height = height;
listView.requestLayout();
}
This function has worked fine so far, but it doesn't compute the correct height for this in getView() in my adapter:
convertView = inflater.inflate(R.layout.activity_frame_no_rounded_corners, null);
activity_frame_no_rounded_corners.xml:
<?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="wrap_content"
android:orientation="horizontal"
android:paddingHorizontal="10dp"
android:focusable="false"
android:background="#drawable/textview_white">
<LinearLayout
android:layout_width="match_parent"
android:focusable="false"
android:layout_height="match_parent">
<ImageView
android:id="#+id/imageview_modify"
android:layout_width="30dp"
android:layout_height="match_parent"
android:layout_gravity="center_vertical"
android:focusable="false"
android:gravity="center_vertical"
android:src="#drawable/ic_baseline_remove_circle_24" />
<LinearLayout
android:layout_width="match_parent"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:focusable="false"
android:layout_height="wrap_content">
<TextView
android:id="#+id/textview_key"
android:text="Key"
android:textSize="15dp"
android:padding="7dp"
android:textColor="#000000"
android:focusable="false"
android:layout_width="0dp"
android:layout_weight="0.4"
android:layout_height="wrap_content"
android:hint="Vlue"/>
<View
android:id="#+id/vertical_bar_devider"
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="#dcdcdc"/>
<EditText
android:id="#+id/edittext_value"
android:text="Value"
android:textSize="15dp"
android:padding="7dp"
android:textColor="#000000"
android:layout_width="0dp"
android:layout_weight="0.6"
android:layout_height="wrap_content"
android:hint="Value"
android:background="#drawable/textview_white"
android:drawableRight="#drawable/ic_baseline_arrow_forward_ios_24_gray"/>
</LinearLayout>
</LinearLayout>
</LinearLayout>
If I use a different xml then it computes the right height. Also, if I remove the weight from the views it also computes the right height (but I need the weight for alignment, I couldn't find a way around it).
You can see in the Screenshot the different list views that I have (one for the names, one for the dob, one for the grade, one for the email, one for the gmc no, one for the specialities).
For testing purposes, they do not have any margins, so they should be one right after the other.
As you can see, the height of the email list view is computed correctly, but my function fails for the rest of the lists. If I change "GMC Number" to "Email" then the function computes the right height for the gmc no list view as well (idk why, it's just an observation).
I guess my problem has something to do with the weight, but I have no idea how to fix it.
Thank you in advance!

Two buttons of same width with several words in one line

I want to draw two Buttons in one line with equal width. Say, they have captions: "Sample text" and "Extra text". They should occupy as low space as possible, but all words should be written.
Now it looks so:
I wrote this code:
<?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">
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:maxLines="1"
android:text="Sample text"
android:textAllCaps="false" />
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:maxLines="1"
android:text="Extra text"
android:textAllCaps="false" />
</LinearLayout>
If I remove android:maxLines="1" and set wrap_content to width, Buttons write a text, but fill different widths.
If you want to locate two buttons on one line, you need to set match_parent to layout_width of LinearLayout
<?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="wrap_content"
android:orientation="horizontal">
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:maxLines="1"
android:text="Sample text"
android:textAllCaps="false" />
<Button
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:maxLines="1"
android:text="Extra text"
android:textAllCaps="false" />
</LinearLayout>
Add layout weight to both buttons. So, it will assure you have the same dimensions for both.
android:layout_weight="1"
Also get screen size and set the size programmatically.
Get Screen width and height
Fixing particular button size will effect small size screens.
Let you want to resize second button.
If a button contains an icon, center it with How to center icon and text in a android button with width set to "fill parent". For instance, move a Button inside a FrameLayout or create a LinearLayout with ImageView and TextView.
If your case is custom view and a button is a FrameLayout with icon, override the following event:
boolean isButtonResized;
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (!isButtonResized) {
int buttonWidth = firstButton.getWidth();
if (buttonWidth != 0) {
isButtonResized = true;
ViewGroup.LayoutParams lp = secondButton.getLayoutParams();
lp.width = buttonWidth;
secondButton.setLayoutParams(lp);
}
}
}
If you have a button without an icon, only text, a resizing will be simplier:
secondButton.setWidth(firstButton.getWidth());

How to use wrap_content with a maximum width?

I am trying to layout a view that should wrap its content, but it shouldn't be more than ~100dp less than its parent width. How can I do that using a RelativeLayout or some other layout? What I have right now will always make the view 100dp less than its parent so that there is space for another view.
This picture is an example of what I have:
As you can see, the text doesn't fill the whole box, so it could be smaller. But, it should never be larger than 100dp less than its parent, so that there is room for the time the message was sent.
This is my layout.
<?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"
android:clipChildren="false"
android:orientation="vertical"
android:paddingBottom="10dp"
android:paddingRight="#dimen/horizontalMargin"
android:paddingTop="10dp">
<TextView
android:id="#+id/message_holder"
android:layout_toLeftOf="#id/blank"
android:layout_alignParentLeft="true"
android:layout_marginLeft="#dimen/horizontalMargin"
android:background="#drawable/message_corners"
style="#style/white_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="alsdkjf; alsdkf" />
<RelativeLayout
android:id="#+id/blank"
android:layout_width="wrap_content"
android:layout_height="1dp"
android:layout_alignParentRight="true"
android:minWidth="100dp">
</RelativeLayout>
<TextView
android:minWidth="100dp"
android:id="#+id/time"
style="#style/gray_text"
android:layout_toRightOf="#id/message_holder"
android:paddingLeft="10dp"
android:text="Yesterday,\n11:30 PM" />
<RelativeLayout
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_alignBottom="#id/message_holder"
android:layout_alignParentLeft="true"
android:background="#drawable/triangle" />
</RelativeLayout>
I have tried using the "minWidth" property on a blank view to the right of the message box to provide spacing, but it doesn't resize to be larger (which would make the message box smaller). When I don't have the blank view, and simply place the time TextView to the right of the message box, then that TextView isn't visible when the message box expands.
Update:
This is my "message_corners.xml":
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid
android:color="#color/green" >
</solid>
<padding
android:left="10dp"
android:top="10dp"
android:right="10dp"
android:bottom="10dp" >
</padding>
<corners
android:radius="10dp">
</corners>
</shape>
Update 2:
This is what I am looking for in a layout with short text:
And this is what I am looking for in a layout with long text:
Here you go, a layout that does exactly what you want.
<?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"
android:clipChildren="false"
android:paddingBottom="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp">
<RelativeLayout
android:id="#+id/blank"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#aaaaaa">
<LinearLayout
android:id="#+id/message_container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingRight="100dp">
<TextView
android:id="#+id/message"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello?"
android:background="#00ff00" />
</LinearLayout>
<TextView
android:id="#+id/time"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/message_container"
android:layout_marginLeft="-100dp"
android:text="12:30 PM"
android:background="#ff0000" />
</RelativeLayout>
</RelativeLayout>
Short message
Long message
I know this is a really old question, but it's a frustrating problem I've encountered several times now and the existing answers weren't quite what I was looking for. Some colleagues and I came up with the following:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#FFFFFF">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#888888"
android:padding="10dp"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#00FF00"
tools:text="Short message."/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="0"
android:background="#CCCCCC"
tools:text="Yesterday,\n11:30pm"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:background="#888888"
android:padding="10dp"
android:orientation="horizontal">
<TextView
android:id="#+id/message_text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#00FF00"
tools:text="Super ultra mega awesome long message which is going to help us take over the world."/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_weight="0"
android:background="#CCCCCC"
tools:text="Yesterday,\n11:31pm"/>
</LinearLayout>
</LinearLayout>
Which looks like this when rendered:
The magic seems to be the zero value for the weight of the text box on the right (in addition to the non-zero weight value of the text box on the left, which some of the other answers already have).
Honestly, I can't explain exactly why it works, but after having looked for a solution to this for so long I'm not questioning it! :)
As an aside, I like this approach because it doesn't require any explicit or minimum widths, any intermediate wrapper views, or the use of clipping settings, margins, padding, etc. to implement view overlay.
What the author of this question really asks is, how to let the TextView expand to fit the message inside of it without overflowing the time TextView, and without leaving blank spaces.
Since you don't actually know the width of the whole screen, you can't tell your TextView to be 100dp less than it.
What you should do is wrap your TextView in a container which will have the toLeftOf rule, with the TextView only wrapping it's contents. This way, the container will expand all the way up to the right (without overflowing the time TextView) but the TextView will only wrap it's text contents (so, it won't extend any blank spaces)
Code
Instead of
<TextView
android:id="#+id/message_holder"
android:layout_toLeftOf="#id/blank"
android:layout_alignParentLeft="true"
android:layout_marginLeft="#dimen/horizontalMargin"
android:background="#drawable/message_corners"
style="#style/white_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="alsdkjf; alsdkf" />
Use
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="#id/blank"
android:layout_alignParentLeft="true"
android:layout_marginLeft="#dimen/horizontalMargin">
<TextView
android:id="#+id/message_holder"
android:background="#drawable/message_corners"
style="#style/white_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="alsdkjf; alsdkf" />
</LinearLayout>
By the way, your layout isn't very good. You should optimize it.
You can try the following arrangement of views and their widths:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="6dp"
>
<FrameLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#android:color/holo_blue_bright"
tools:text="Some long test is this which is support to wrap at the end of parent view"
/>
</FrameLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
tools:text="Yesterday,\n 11:30 PM"
/>
</LinearLayout>
Sat Sri Akal
This can also be achieved using ConstraintLayout
with 2 children in horizontal chain
1st child
layout width 0
constraint weight 1
constraint max width wrap
2nd child
layout width wrap content
A solution with ConstraintLayout using
app:layout_constrainedWidth
layout_constraintHorizontal_bias
layout_constraintHorizontal_chainStyle
.
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="#+id/edt_left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Sample content"
app:layout_constrainedWidth="true"
app:layout_constraintEnd_toStartOf="#id/button_right"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/button_right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Right Button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/edt_left"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
If you want to make time text on right and text message on its left, you can do something like that ( using this in relative layout) also you can use maxWidth not minWidth
<TextView
android:id="#+id/view_textView_timeText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="#id/view_textView_timeText"
android:maxWidth="100dp"/>
What you could do is put an empty view between the 2 views and keep its width as MATCH_PARENT and assign the textview to leftof this empty view and the empty view to left of the date view. Just make sure to keep the view empty.
As i understand you want to make the layout or the textview to be 100 dp less than the screen size
Which you can do by getting the screen width in pixels which is done by this
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
Then you could set the textbiew width to be less 100dp from the screen size hope this help
P.s I think you might want to convert dp to px but i am not sure
You can do like this(not the direct answer for the question ):
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="bottom"
android:orientation="horizontal">
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:paddingLeft="45px"
android:text="asdfadsfsafasdfsakljkljkhjhkkhjkjhjkjhjkhjkhljkhlkhjlkjhljkhljkhlkjhljkhljkhlfasd"
android:textColor="#4a4a4a"
android:textSize="40px" />
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:maxLines="1"
android:paddingLeft="45px"
android:paddingRight="48px"
android:text="2017.08.09 13:00"
android:textColor="#9b9b9b"
android:textSize="34px" />
</LinearLayout>
I have a common solution to solve this kind of layout question:
Create a specific ViewGroup!
For the question above, the key point is how to set the correct maxWidth to the content view.
Create a SpecialViewGroup. The contentView is the left view, and the timeView is the right view.
class SpecialViewGroup #JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : LinearLayout(context, attrs, defStyleAttr) {
private lateinit var contentView: TextView
private lateinit var timeView: TextView
override fun onAttachedToWindow() {
super.onAttachedToWindow()
contentView = findViewById(R.id.content)
timeView = findViewById(R.id.time)
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
// measure the timeView firstly, because the contentView's maxWidth rely on it.
timeView.measure(
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
)
// then caculate the remained space for the contentView
val parentWidth = MeasureSpec.getSize(widthMeasureSpec)
val paddingHorizontal = paddingStart + paddingEnd
val view1MaxWidth = parentWidth - timeView.measuredWidth - paddingHorizontal
// set the maxWidth to the contentView
contentView.maxWidth = view1MaxWidth
// The rest thing will be handed over by LinearLayout
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
}
Use the SpecialViewGroup in your layout, like the usual LinearLayout.
<com.example.SpecialViewGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFBB86FC"
android:orientation="horizontal"
android:padding="10dp">
<TextView
android:id="#+id/content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#FF3700B3"
android:padding="10dp"
android:text="adaasdasdasasdadasdasdaaaaaaaaaaaaaaaa"
android:textColor="#color/white" />
<TextView
android:id="#+id/time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#FF018786"
android:padding="10dp"
android:text="1970-01-01"
android:textColor="#color/white" />
</com.example.archview.SpecialViewGroup>
And the result:
The benefits of this approach are obvious:
No extra nesting Layout.
Common to solve the similar layout questions.
Had the similar issue. Made it works with constraint.
<ConstraintLayout>
<TextView
android:id="#+id/title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="2"
app:layout_constraintEnd_toStartOf="#+id/option_info"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_max="wrap" />
<ImageView
android:id="#+id/option_info"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/ic_info"
app:layout_constraintBottom_toBottomOf="#+id/title"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#+id/title"
app:layout_constraintTop_toTopOf="#+id/title" />
</ConstraintLayout>

Maintain textview height in LinearLayout

I have two TextViews in LinearLayout. Layout orientation is in horizontal. I have to maintain both Textview height as equal. But as per text length both are shown in different height.
I had tried to make the same text length like below
public static String padRight(String s, int n) {
return String.format("%1$-" + n + "s", s);
}
But height is bit different. How do i solve this ?
If I didn't misunderstand you you want to TextViews inside a horizontal oriented LinearLayout, and both TextViews must in same height.
Then use a layout something like below:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="#+id/textView1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#B40431"
android:text="text sample\ntext sample\ntext sample\ntext sample\ntext sample\ntext sample\n"
android:gravity="center_vertical"/>
<TextView
android:id="#+id/textView2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="#0000FF"
android:text="text sample\ntext sample\ntext sample"
android:gravity="center_vertical"/>
</LinearLayout>
Output is going to be this:
Because the text is long textview getting bigger So You set the singleLine true of your textView then it will work,
Add this line in your Textview xml:--
android:singleLine="true"
hope it helps you..

ImageButton: Force square icon (height = WRAP_CONTENT, width = ?)

In my horizontal LinearLayout I have a TextEdit and an ImageButton. The ImageButton is as high as the TextEdit.
I'd like that the ImageButton is exactly as wide as it's long.
At the moment it looks like the width of the ImageButton is like when there is no scaling (ImageButton width [px] = unscaled drawable width [px]):
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<EditText
android:id="#+id/txtName"
android:layout_width="1dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<ImageButton
android:id="#+id/btSet"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:scaleType="fitEnd"
android:src="#drawable/pin2" />
</LinearLayout>
How it should look like:
Try this, I think this should work:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal" >
<ImageButton
android:id="#+id/btSet"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:scaleType="centerInside"
android:adjustViewBounds="true"
android:src="#drawable/pin2" />
<EditText
android:id="#+id/txtName"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toLeftOf="#id/btSet" />
</RelativeLayout>
Explaination: centerInside will assure that the image will scale proportionally within the bounds of the ImageButton. adjustViewBounds="true" will...well, adjust the view's bounds, if the image needed to be scaled.
try adding
adjustViewBounds="true"
to the ImageButton, that should clip the excess width
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<EditText
android:id="#+id/txtName"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<ImageButton
android:id="#+id/btSet"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="#drawable/pin" />
</LinearLayout>
Use
android:scaleType="fitCenter"
or android:scaleType="centerInside"
in the ImageButton in xml File.
I might be a bit late to the party.
However there's an easy way to achieve this behavior by overriding the onMeasure().
Here's how it'd look like :
public class MySquareImageButton extends ImageButton {
public MySquareImageButton(Context context) {
super(context);
}
public MySquareImageButton(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MySquareImageButton(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//(1)if you want the height to match the width
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
//(2)if you want the width to match the height
//super.onMeasure(heightMeasureSpec, heightMeasureSpec);
}
}
And then you'd simply replace your XML's ImageButton with this custom one :
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<EditText
android:id="#+id/txtName"
android:layout_width="1dp"
android:layout_height="wrap_content"
android:layout_weight="1" />
<com.whatever_your_package.MySquareImageButton
android:id="#+id/btSet"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:scaleType="fitEnd"
android:src="#drawable/pin2" />
</LinearLayout>
You'd simply put wrap_content to width or height, depending on which one you want to dictate the size of your button.
In the case you want your button to wrap its height to the image, and that the width simply matches the height, you'd use
android:layout_width="wrap_content"
android:layout_height="wrap_content"
and use
//(2)if you want the width to match the height
//super.onMeasure(heightMeasureSpec, heightMeasureSpec);
I had the same problem.
I was trying to create something that looked like this:
But what I was getting was this:
The ImageButton was getting stretched horizontally.
All the top answers didn't work for me. But I noticed people mentioning layout_weight and just looked it up out of curiosity and found the following on Android docs:
Layout Weight
LinearLayout also supports assigning a weight to individual children with the android:layout_weight attribute. This attribute assigns an "importance" value to a view in terms of how much space it should occupy on the screen. A larger weight value allows it to expand to fill any remaining space in the parent view. Child views can specify a weight value, and then any remaining space in the view group is assigned to children in the proportion of their declared weight. Default weight is zero.
For example, if there are three text fields and two of them declare a weight of 1, while the other is given no weight, the third text field without weight will not grow and will only occupy the area required by its content. The other two will expand equally to fill the space remaining after all three fields are measured. If the third field is then given a weight of 2 (instead of 0), then it is now declared more important than both the others, so it gets half the total remaining space, while the first two share the rest equally
So basically, if you set the layout_width to be 0 for an element, it'll appear according to the dimensions of its content.
If you set it to anything else, the element will fight for extra space in the parent element that contains it; with more weighted elements taking up more space.
So, when I set layout_width = 0 for both TextView and ImageButton in my example, neither of them takes up any extra space and they both huddle up to the left.
But when I set it to 1 for TextView and 0 for ImageButton, the ImageButton doesn't take any more space than required by its content; while the TextView takes up all the extra space and pushes ImageButton to the right.
Just the way I want it.
Initially, what had happened was both the elements were set to have a default layout_weight of 1 and hence both were equally competing for the extra space.
Simply use the weightSum to devide the size of controls accordingly...
<?xml version="1.0" encoding="utf-8" ?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="fill_parent"
android:layout_height="fill_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="1.0" >
<EditText
android:id="#+id/txtName"
android:layout_weight="0.8"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:inputType="text"
android:singleLine="true"/>
<ImageButton
android:id="#+id/btSet"
android:layout_weight="0.2"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:scaleType="fitEnd"
android:src="#drawable/pin2" />
</LinearLayout>
</LinearLayout>
Hope it will help you.
as you want your ImageButton is stretchable & exactly as wide as it's long, its better to use NinePatch Image. you may find help form here Draw 9-patch & How does Android’s nine-patch tool work ?
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="1.0" >
<EditText
android:id="#+id/txtName"
android:layout_weight="0.75" // this work like percentage adjust as u want 70 or 75
android:layout_height="wrap_content"
android:layout_width="0dp"
android:inputType="text"
android:singleLine="true"/>
<ImageButton
android:id="#+id/btSet"
android:layout_weight="0.25" // this work like percentage adjust as u want 25 or 30
android:layout_height="wrap_content"
android:layout_width="0dp"
android:scaleType="fitEnd"
android:src="#drawable/pin2" />
</LinearLayout>
Just add the following line to your ImageButton and the extra background will fade away:
android:layout_gravity="center|clip_horizontal"
hope this works
Just ran into something like this and the other suggestions didn't help. What did help was setting the padding in the ImageButton:
android:padding="5dp"
Besides that, I didn't touch the original layout. The button became square on the 3 emulators that I tested (3.2, 4.4.2, 5.1)
I tried myself,it works
Simply do the Following...
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="#+id/editText1"
android:layout_width="0dp"
android:layout_weight="5"
android:layout_height="wrap_content"
android:inputType="text"/>
<ImageButton
android:id="#+id/imageButton"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent" />
</LinearLayout>
Use Layout Weight ratio 5:1 inside a LinearLayout for EditText and ImageButton
You Can resize the Image button using px... like below...
`android:layout_width="5px"
android:layout_height="5px"`

Categories

Resources