I'm new to Android, please help me to design below layout. Many thanks.
I want to implement a layout, it shows a text followed by a counter. If the text is too long, show ... followed by counter. like below:
Expected layout:
Short text (3) // when screen width is enough
Long text blah bl...(2) // when screen width isn't enough
Below are my xml. It shows normally for above 1, when text is short. When text is long, the problem are:
1) it doesn't show "..." at the end of text
2) counter (2) isn't shown on screen.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_weight="1"
>
<TextView android:id="#+id/text" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="very long body safbadaf asfasf safasfd"
android:layout_gravity="left"
android:paddingLeft="4dp" android:paddingTop="8dp"
android:paddingRight="4dp" android:paddingBottom="8dp"
android:textStyle="bold" android:singleLine="true" android:ellipsize="end"/>
<TextView android:id="#+id/count" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:text="count"
android:layout_gravity="center_horizontal"
android:paddingLeft="4dp" android:paddingTop="8dp"
android:paddingRight="4dp" android:paddingBottom="8dp"
android:textStyle="bold" android:singleLine="true" android:layout_weight="1" />
</LinearLayout>
William
set android:layout_weight="1" for the first textview and not the second one. Also set layout_width="0" for the first textview instead of wrap_content
Related
I have the next bad design for Android:
I need to keep More infos with the icon to the right of the black text. If Item 1 of 1 will be a longer string, it'll push the icon+text to the right. My problem which I can't figure out is if the left text it too long to fit in one line, i'd like it for More infos to be pushed until the right edge of its parent and stay there and the left black text should jump to a new line.
But this is not HTML for it to act like that ! :) Any ideas on how I could accomplish this ?
I'm really thinking of asking the designer to change the design.
EDIT
What I've done for it to look like above:
<RelativeLayout ...>
<!--TEXT-->
<TextView
android:id="#+id/list_item_form_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="#dimen/app_spacing_x0_5"
android:layout_marginTop="#dimen/app_spacing_x3"
android:textColor="#color/app_black"
android:textSize="#dimen/app_text_tiny" />
<!--VIEW DETAILS-->
<TextView
android:id="#+id/list_item_view_details_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="50dp"
android:layout_toRightOf="#id/list_item_form_text"
android:layout_alignTop="#id/list_item_form_text"
android:drawableLeft="#drawable/ic_camera"
android:drawablePadding="#dimen/app_spacing_x0_3"
android:text="#string/f_form_front_view_details" />
</RelativeLayout>
You can achieve that with a LinearLayout:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="test"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="123444"/>
</LinearLayout>
The key is having the Linear Layout with wrap_content and the first view with weight=1 and width=0dp
Maybe something like this:
<!--TEXT-->
<TextView
android:id="#+id/list_item_form_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginTop="5dp"
android:text="Long long long long text Long long long long text"
android:layout_toStartOf="#+id/list_item_view_details_btn"
android:layout_alignParentStart="true"/>
<!--VIEW DETAILS-->
<TextView
android:id="#+id/list_item_view_details_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="50dp"
android:layout_alignParentEnd="true"
android:layout_alignTop="#id/list_item_form_text"
android:text="More infos"/>
The result is:
So, idea in this: I have two TextViews, first can expand whatever it wants, second always 5 chars (time). Problem is in that first TextView can easily push second out of the screen.
So, what I need is something like adjustable LinearLayout, or maybe some GridLayout that will move second TextView on some sort of second line if it doesn't fit parent.
For example you can watch at message bubbles in Viber and WhatsApp. Thanks for any advise.
Update 1
Here is XML that i have now (Only message part)
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/messageBox"
android:layout_gravity="center_vertical"
android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Medium"
android:textColor="#color/black"
android:text='#{mess.message}'/>
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_vertical|end"
android:gravity="center_vertical|end"
android:paddingLeft="8dp"
android:textSize="12sp"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Small"
android:text='#{Utils.parseMillsToHoursAndMins(mess.date)}'/>
</LinearLayout>
Update 2
So I added layout_weight to first TextView, that helped with my first problem, but now I have new one. This two TextViews are in LinearLayout which is in another LinearLayout with another TextView. Parent LinearLayout have width set to wrap_content so if top TextView will be bigger than 2 TextViews it will cause child LinearLayout to be less than it's parent, and 2nd TextView (from that 2) wouldn't be in the end of parent. But when child LinearLayout is bigger, all appears to be OK. I know it's complicated, so this is XML
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="0dp"
android:id="#+id/contentPanel"
app:bringToFront="#{true}"
android:orientation="vertical"
android:background="#{(mess.isMine?#drawable/chat_bubble_right:#drawable/chat_bubble_left)}">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text='#{!mess.authorRole.equals("Client")?(mess.authorRole + " - " + mess.author):mess.author}'
android:textColor='#{mess.authorRole.equals("Lawyer")?#color/colorPrimary:mess.authorRole.equals("Admin")?#color/red:#color/green}'
android:textSize="12sp"
android:id="#+id/author"
android:fontFamily="sans-serif-medium"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Small"/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/messageBox">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:layout_weight="0.7"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Medium"
android:textColor="#color/black"
android:text='#{mess.message}'/>
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:paddingLeft="8dp"
android:textSize="12sp"
android:gravity="bottom|end"
android:textAppearance="#style/Base.TextAppearance.AppCompat.Small"
app:checkFit="#{false}"
android:text='#{Utils.parseMillsToHoursAndMins(mess.date)}'/>
</LinearLayout>
</LinearLayout>
The new approach for achieving such behaviour is using ConstraintLayout with Flow. Here is an example of usage:
<androidx.constraintlayout.helper.widget.Flow
android:id="#+id/socialsButtonsFlow"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
app:flow_horizontalGap="8dp"
app:flow_verticalGap="4dp"
app:flow_wrapMode="aligned"
app:flow_horizontalStyle="spread_inside"
app:constraint_referenced_ids="vkButton,twitterButton,facebookButton,youtubeButton,instagramButton,odnoklassnikiButton,tiktokButton"
app:layout_constraintEnd_toEndOf="#id/socialsLabel"
app:layout_constraintStart_toStartOf="#+id/socialsLabel"
app:layout_constraintTop_toBottomOf="#+id/socialsLabel" />
For small screens it looks like this:
I am not sure this will help you or not but:
Use: https://github.com/ApmeM/android-flowlayout
<org.apmem.tools.layouts.FlowLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
</org.apmem.tools.layouts.FlowLayout>
Inside FlowLayout you can put your view's and it will auto move to next line if not fit.
if your textviews in linearlayout you can add weightSum method
I have a LinearLayout which contains two TextViews. Let the first TextView's text be "short text" and the 2nd TextView's text be "(s)".
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="#+id/variable-size"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:ellipsize="middle"
android:lines="1"
android:singleLine="true"
android:text="short text"/>
<TextView
android:id="#+id/fixed-size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:ellipsize="none"
android:lines="1"
android:singleLine="true"
android:text="(s)" />
</LinearLayout>
I want the LinearLayout to appear to the user thus:
[[short text][(s)]____________]
where ____ means empty view.
Now if I put a slightly longer string into the first TextView, I want to see this:
[[slightly longer text][(s)]__]
and if I put a much longer string into the first TextView, I want to see this:
[[really long ...ng text][(s)]]
But I can't seem to find a way to keep the first TextView from crowding out the second TextView altogether, like so:
[[really long lo... long text]]
How do I get the behavior I am looking for?
The base of the answer to your question is this:
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:orientation="horizontal">
<TextView
android:id="#+id/variable-size"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:ellipsize="middle"
android:lines="1"
android:singleLine="true"
android:text="short text" />
<TextView
android:id="#+id/fixed-size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:ellipsize="none"
android:lines="1"
android:singleLine="true"
android:text="(s)" />
</LinearLayout>
BUT... bare in mind that I changed the width of your LinearLayout from:
android:layout_width="0dp"
android:layout_weight="1"
to
android:layout_width="wrap_content"
and that's a really important part of the answer.
The code I presented works like this:
[[short text][(s)]]
[[slightly longer text][(s)]]
[[really long ...ng text][(s)]]
It manages the ellipsizing correctly, but cannot introduce the "empty view" (____). If I didn't change the LinearLayout's layout_width, the ellipsizing would work correctly ((s) wouldn't be pushed off the screen), but the text alignment wouldn`t be correct. It would look like this:
[[short text ][(s)]]
[[slightly longer text ][(s)]]
[[really long ...ng text][(s)]]
So if the "empty view" is a need for you, you will need to implement it (for example) with nesting your LinearLayout inside another one (and this time "empty view" is gonna be an actual View). Like so:
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/variable-size"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"
android:ellipsize="middle"
android:lines="1"
android:singleLine="true"
android:text="short text" />
<TextView
android:id="#+id/fixed-size"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:ellipsize="none"
android:lines="1"
android:singleLine="true"
android:text="(s)" />
</LinearLayout>
<View
android:id="#+id/empty_view"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_weight="1" />
</LinearLayout>
This will give you the following behaviour:
[[[short text][(s)]]____________]
[[[slightly longer text][(s)]]__]
[[[really long ...ng text][(s)]]]
I am new to Android, i have below task.
I want to align three TextViews adjacent to each other with ellipsis if the text is too long . Currently i am using below code which aligns my TextView adjacent to each other, but my problem is if the text is too long, the below code not putting the ellipsis. i got some trick to use both toleftof and torightof from here, but in my case it going to circular dependency as mentioned here.
<RelativeLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_toRightOf="#+id/reminderText">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/noteTagOne"
android:ellipsize="end"
android:singleLine="true"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/noteTagTwo"
android:ellipsize="end"
android:singleLine="true"
android:layout_toRightOf="#+id/noteTagOne"
android:layout_marginLeft="5sp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/noteTagThree"
android:layout_toRightOf="#+id/noteTagTwo"
android:ellipsize="end"
android:singleLine="true"
android:layout_marginLeft="5sp"/>
</RelativeLayout>
I want output as,
Tag1... Tag2... Tag3...
Basically, i want some ideas, whether in xml i can achieve this or need to do it programmatically, since TextView text's are dynamic i cannot fix maxLength, sometimes only single tag may exist, at that time it should take full text.
Note: I am developing Android project using C# in Xamarin.
Added code is for the above highlighted part. I fixed overlapping of tagsicon & text. Now only two issues.
1) Last tag is overlapping with right aligned image.
2) If TextView texts are short, gap is shown in-between the tags
How to fix it?
try this solution
<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="match_parent"
android:orientation="horizontal"
tools:context=".MainActivity" >
<TextView
android:id="#+id/noteTagOne"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxWidth="100dp"
android:singleLine="true"
android:text="Tag111111111111111111"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/noteTagTwo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5sp"
android:layout_toRightOf="#+id/noteTagOne"
android:ellipsize="end"
android:maxWidth="100dp"
android:singleLine="true"
android:text="Tag2222222222222222"
android:textAppearance="?android:attr/textAppearanceLarge" />
<TextView
android:id="#+id/noteTagThree"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5sp"
android:layout_toRightOf="#+id/noteTagTwo"
android:ellipsize="end"
android:maxWidth="100dp"
android:singleLine="true"
android:text="Tag3333333333333333"
android:textAppearance="?android:attr/textAppearanceLarge" />
Use this android:ellipsize="marquee" it will work
android:ellipsize="marquee"
or
android:ellipsize="end"
android:maxLines="1"
android:scrollHorizontally="true"
android:singleLine="true"
I need to display two single-line TextViews horizontally. The left TextView (let's name it 1) may have a longer text which may shortened and finished with "...". The right text view (2) has a short text and should never get shortened.
I want the 1 to remain aligned to the left end of the parent. The 2 aligned to the right side of 1.
There are now 2 conditions that I have to meet
a) if the 1 has a short text then the 2 should get aligned to the right of 1 (none of the gets shortened).
b) but if the 1 has a too long text then the text of 1 should be shortened by '...' while the view 2 is moved maximally to the right of the parent but still remains fully visible (no ...)
My current solution is the following below. The scenario b) is fine with mine, but in case of a) the problem is that the view 2 is moved to the right side of the parent and the 1 to the left side - both are short and there's pretty much space in between which looks odd. I want 2 to move to the further left (next to 1) and leave this space on the right side.
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_marginTop="1dp"
android:layout_weight="0.5">
<TextView
android:id="#+id/ns_in_txt"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:gravity="top|left"
android:maxLines="1"
android:singleLine="true"
android:textColor="#00a2ff"
android:textSize="18sp" />
<TextView
android:id="#+id/ns_txt"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="#id/ns_in_txt"
android:gravity="top|left"
android:maxLines="1"
android:singleLine="true"
android:textColor="#00a2ff"
android:textSize="18sp" />
</RelativeLayout>
Try doing this
<RelativeLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_context"
android:layout_marginTop="1dp">
<TextView
android:id="#+id/ns_in_txt"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:layout_alignParentRight="true"
android:gravity="left"
android:maxLines="1"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#00a2ff"
android:textSize="18sp" />
<TextView
android:id="#+id/ns_txt"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="#id/ns_in_txt"
android:gravity="left"
android:maxLines="1"
android:singleLine="true"
android:textColor="#00a2ff"
android:textSize="18sp" />
</RelativeLayout>
Apparently, you want two scenarios which require to set a different orientation to the parent layout: first horizontal, second vertical. Maybe I'm wrong (and I hope so but) in static xml, there will be difficult to do this.
Try the code below to test if I'm wrong:
Scenario 1: orientation horizontal = the text 1 is not big enough
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="1dp"
android:orientation="horizontal" >
<TextView
android:id="#+id/textLong"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#00a2ff"
android:textSize="18sp"
android:text="This is a normal text not big" />
<TextView
android:id="#+id/textShort"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:singleLine="true"
android:textColor="#00a2ff"
android:textSize="18sp"
android:text="short text" />
</LinearLayout>
Scenario 2: orientation vertical = the text 1 is too big
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="1dp"
android:orientation="vertical" >
<TextView
android:id="#+id/textLong"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:ellipsize="end"
android:singleLine="true"
android:textColor="#00a2ff"
android:textSize="18sp"
android:text="This is a biiiggg loooonnng teeeeexxxxxtttt" />
<TextView
android:id="#+id/textShort"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:singleLine="true"
android:textColor="#00a2ff"
android:textSize="18sp"
android:text="short text" />
</LinearLayout>
To resolved your issue, you can try 2 solutions.
First, try to create a maxLenght limit, which calculate in your Activity and change the parent orientation of the LinearLayout. Get the number of chars that you have and display the orientation as well.
Second, customise your own class extend TextView. And create a getWidth method which return the width of the long TextView in comparison to it parent and change the orientation.
Maybe the following questions/answers could be useful (I think there are not solutions but more as inspiration):
In Android how to get the width of the Textview which is set to Wrap_Content
Get the size of a text in TextView
How to find android TextView number of characters per line?
Auto Scale TextView Text to Fit within Bounds
EDIT:
I found a solution with the last url that I writed above. See this answer where the dev wanted to make the same as you. So he decided to create a autoresizable textview. Take a look here: Move two side by side textviews to be one under another if text is too long
I hope this will help you.
May I suggest to use combination of LinearLayout and a little bit of coding. The idea is to have them side by side regardless of the size. and after the right textview is measured and laid out, set the max width of the left textview to whatever space left.
Here is the layout file, nothing special here:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:id="#+id/ns_in_txt"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:ellipsize="end"
android:gravity="top|left"
android:maxLines="1"
android:singleLine="true"
android:textColor="#00a2ff"
android:textSize="18sp" />
<TextView
android:id="#+id/ns_txt"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:ellipsize="none"
android:gravity="top|left"
android:maxLines="1"
android:singleLine="true"
android:textColor="#00a2ff"
android:textSize="18sp" />
</LinearLayout>
and add some codes to the activity/fragment:
final TextView tvLeft = (TextView) findViewById(R.id.ns_txt);
final TextView tvRight = (TextView) findViewById(R.id.ns_in_txt);
ViewTreeObserver obs = tvRight.getViewTreeObserver();
obs.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
tvLeft.setMaxWidth(SCREEN_WIDTH - tvRight.getWidth());
}
});