I got the following customViews:
val paintTextTypology = Paint()
val paintTextDate = Paint()
This 2 texts are the following customViews:
And the result I want to achieve is this:
So I want to align the text to right, but since the texts are separated, I think I have to create a dynamic RelativeLayout to align them to the right of the parent.
(I can't afford to have margin-right because the text can change.)
How can I do it?
Based on your comment (not 100% clear to me yet because I don't know what your custom views are), I would use a ConstraintLayout that would look like this:
The red rectangle is your picture.
And then I added two textViews which are aligning to the image. You can play with it and see what else you need. (this is a simplification).
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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"
>
<TextView
android:id="#+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is textView One"
app:layout_constraintEnd_toStartOf="#id/image"
app:layout_constraintTop_toTopOf="#+id/image"
/>
<TextView
android:id="#+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is textView Two -> longer"
app:layout_constraintEnd_toStartOf="#id/image"
app:layout_constraintTop_toBottomOf="#id/text1"
/>
<ImageView
android:id="#+id/image"
android:layout_width="150dp"
android:layout_height="300dp"
android:contentDescription="TODO"
android:src="#color/emphasis_red"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
</android.support.constraint.ConstraintLayout>
This would look like this:
Related
The situation is: I have a constraint layout with 3 TextViews in a row
<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:layout_marginBottom="10dp"
android:id="#+id/constraint"
tools:context=".MainActivity">
<TextView
android:id="#+id/small"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:text="5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/medium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Some text, not too long"
android:layout_marginStart="10dp"
app:layout_constraintStart_toEndOf="#id/small"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/big"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text, that can be extremely long, but can be also short"
android:layout_marginStart="10dp"
app:layout_constraintStart_toEndOf="#id/medium"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
The last textView can be very long and when it is, I would like to move this textView under textView with id medium, so that the text in the text view is not separated. That means, I do not want to display text within a textView on two lines, I want to have text displayed in one line. If the text is short: on the same level as other textViews(picture 1), if the text is too big to fit the screen, the whole textView should be displayed under the second textView(#+id/medium) - picture 2.
Is it in general possible to do so? If yes, I would appreciate it, if you give me some hints.
With what I tried to do I can only move the rest of the text to a new line and display the textView in two lines, but that is not what I really want to see.
Standard situation, when text is not too big:
What I would like to have if the text is too big:
You can use Flow (no not that one) which is a flexbox-style layout helper for 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:id="#+id/constraint"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
tools:context=".MainActivity"
tools:ignore="MissingConstraints">
<androidx.constraintlayout.helper.widget.Flow
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:constraint_referenced_ids="small, medium, big"
app:flow_horizontalBias="0"
app:flow_horizontalGap="10dp"
app:flow_horizontalStyle="packed"
app:flow_wrapMode="chain"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/small"
android:layout_width="wrap_content"
android:layout_height="20dp"
android:text="5" />
<TextView
android:id="#+id/medium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Some text, not too long" />
<TextView
android:id="#+id/big"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Text, that can be extremely long, but can be also short" />
</androidx.constraintlayout.widget.ConstraintLayout>
It basically just lets you define a chain of elements and handles their constraints (note the tools:ignore="MissingConstraints" in the main layout, you don't put them on the views themselves) and then you can set it to wrap when things go off the screen, etc. There are a bunch of tweaks you can do, like setting a max number of elements on a line, forming an aligned grid, etc
There's a pretty good visual guide here:
https://proandroiddev.com/awesomeness-of-constraintlayout-flow-aa0b5edd5df
I have 2 views in a layout - TextView and Button. TextView is aligned/anchored to the left side and the button is to the right side.
What I'm trying to achieve is the natural "wrap behavior" of the Button. When TextView will be wide enough so that there won't be space for the button (in the same line), it should move below the TextView, while still anchored to the right.
Here are 3 scenarios for the layout which I want to achieve:
I was trying to make this with FlexBoxLayout, but the button appears on the left side after wrapping.
<com.google.android.flexbox.FlexboxLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:flexDirection="row"
app:flexWrap="wrap"
app:justifyContent="space_between"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="text text"
android:gravity="start"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="end"
android:text="Button"
/>
</com.google.android.flexbox.FlexboxLayout>
So how can I do that? It doesn't need to be FlexBox, I can use any layout, even 3rd party.
Use justifyContent="flex_end" in the parent and set layout_flexGrow to the children like this works for me.
<com.google.android.flexbox.FlexboxLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="300dp"
android:layout_height="wrap_content"
app:flexDirection="row"
app:flexWrap="wrap"
app:justifyContent="flex_end">
<TextView
android:id="#+id/textview2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="blah blah"
app:layout_flexGrow="1" />
<TextView
android:id="#+id/textview3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:text="( . )( . )"
app:layout_flexGrow="0" />
</com.google.android.flexbox.FlexboxLayout>
No need for a 3rd party layout.
ConstraintLayout should be more than enough - with a small tweak in code.
Your TextView will have straightforward constraints, set to parent layout (start, top, end).
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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"
xmlns:tools="http://schemas.android.com/tools">
<TextView
android:id="#+id/text"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:text="Text text text text text text" />
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="#+id/text" />
</android.support.constraint.ConstraintLayout>
In the code, just check the width of the TextView and compare it with the width of the parent (basically check it should overlap with the button).
If it does change(you will have to do this in code but this is the principle):
app:layout_constraintTop_toTopOf="#+id/text"
to
app:layout_constraintTop_toBottomOf="#+id/text"
If you need to do this dynamically ConstraintLayout has neat feature "Keyframe animations" that creates awesome looking animations when you are changing constraints.
Doesn't seem like there is a way to do it with Flexbox. I would just do it programmatically when you've inflated the resource (in onCreateView() or something like that). The parent of both of the views would be a RelativeLayout, with the Button aligned to the TextView top when the widths combined don't exceed the width of the RelativeLayout, and aligned to the bottom of the TextView when the widths are larger than that.
I have an arbitrary length textview+icon (icon+text) that needs centering on the screen. On the same row, there is a button aligned to the right side of the screen. (X)
| icon+text | X |
Using a LinearLayout I can center it with the view, but the button on the right shifts it left.
With a relative layout, I can achieve what I want but if the text is too long the button overlaps the text.
What's the right way to do this? I haven't used constraintLayout before, would that solve it?
I suggest you to use a constraint layout,
Example:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context=".YourActivity">
<TextView
android:id="#+id/my_text_view"
android:text="My Long Text That must not overlap the button"
android:layout_width="0dp"
android:gravity="center"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="8dp"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="#+id/my_btn"
app:layout_constraintTop_toTopOf="#+id/my_btn"
app:layout_constraintBottom_toBottomOf="#+id/my_btn"/>
<Button
android:id="#+id/my_btn"
android:layout_marginTop="16dp"
android:text="My Nice Button "
android:layout_marginEnd="8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="#id/my_text_view"
app:layout_constraintEnd_toEndOf="parent"/>
</android.support.constraint.ConstraintLayout>
Example Output:
You can set it like this,
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.2"
android:drawableLeft="#mipmap/ic_launcher"
android:text="Click" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.8"
android:gravity="center"
android:text="TextView" />
</LinearLayout>
just use a Relative Layout.
Center your Textview
and put toRightOf=txtViewsName on the button.
//UPDATED Forcing Widths in DP to ensure text is always centered and never overlaps button.
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="#mipmap/ic_launcher"
android:maxWidth="230dp"
android:layout_centerHorizontal="true"
android:ellipsize="end"
android:text="My text to show test abcdefghyijkldkf here" />
<Button
android:layout_width="80dp"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:text="Button" />
</RelativeLayout>
You will need to adjust the button width and textview maxwidth to match your design, and confirm on preview all resolutions, but dp should cover you pretty well in this case.
NOTE*
This simply answers your issue, but does not do any funny behavior, i.e. if text grows too much ignore center command and start moving to the left, this does not do that. If that is your desire, please update your question.
//Centering Text in left view and using weight to ensure text area takes proper percentage of the space (based on your comments, not the layout you are looking for, but I'll leave it in case it helps someone else).
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:weightSum="10">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="7"
android:drawableLeft="#mipmap/ic_launcher"
android:gravity="center"
android:text="My text to show here" />
<Button
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="3"
android:text="Button" />
</LinearLayout>
for best practice i think ConstraintLayout is the best solution for designing and yes of course it helps you for what are you looking for.
for more info check this Build a Responsive UI with ConstraintLayout and this
ConstraintLayout.
Since your ImageButton on right has a fixed width (let's say 40dp for the purpose of this example) you can achieve the desired result by adding a margin of the same width at the end of your TextView to ensure that they're not overlapping. To keep the TextView centered on the screen you have to add the same margin at the start as well:
<android.support.constraint.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="wrap_content">
<TextView
android:id="#+id/textview"
android:text="TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="40dp"
android:layout_marginEnd="40dp"
app:layout_constrainedWidth="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ImageButton
android:id="#+id/button"
android:layout_width="40dp"
android:layout_height="40dp"
app:layout_constrainedWidth="true"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintVertical_bias="0.0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="#id/textview"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
If you want to center the text within the TextView use android:gravity="center":
If the ImageButton's width was wrap_content then this approach wouldn't work, because there is no way to constraint the end of the TextView both to the end of the parent (so it's centered on the screen) and to the start of the ImageButton (so they don't overlap if the text gets long) at the same time.
In the end I ended up using RelativeLayout per Sam's suggestion with maxWidth and margin set on the TextView.
I have this layout, where I have text view and an icon next to it.
However, the text is dynamically changing, so sometime it will be too long which push the icon out of the screen.
I tried to add weight to the text but it makes the icon on the right side of the screen which I don't want, I just want it right after the text even if the text go to the next line.
There is my code:
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/Text"
android:layout_marginLeft="25dp"
android:text="llllll"
/>
<android.support.v7.widget.AppCompatImageButton
android:id="#+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:background="#android:color/transparent"
android:src="#drawable/ic_arrow_drop_down_black_24dp" />
</LinearLayout>
any idea :(?
You can use ConstraintLayout to handle this.
<android.support.constraint.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">
<TextView
android:id="#+id/text"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="#+id/image"
app:layout_constraintWidth_default="wrap"/>
<ImageView
android:id="#+id/image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toRightOf="#+id/text"
app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>
Just simply add one property line in textview "android:maxWidth" like below :
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/Text"
android:layout_marginLeft="25dp"
android:text="llllll"
android:maxWidth="100dp" //it can be your specific size
/>
<android.support.v7.widget.AppCompatImageButton
android:id="#+id/icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="10dp"
android:background="#android:color/transparent"
android:src="#drawable/ic_arrow_drop_down_black_24dp" />
</LinearLayout>
You could use <img> tags in the HTML
to know how to do that see this qution (is-it-possible-to-display-inline-images-from-html-in-an-android-textview)
Put the text view inside a relative layout with match parent as width and height wrap content.
Set text view to the same dimensions ie march parent as width and height as wrap content.
Have the image button in the same relative layout and use alignParentEnd as true. You'll see it always add the end of your text view.
If you choose to do this, set some maxEms and ellipsize end so that the text does not overlap the button. You'll get the value by testing it yourself, depends on the text size usually.
Since you want it as a button I'm suggesting this. If you want it just be an icon with no use, you should look into drawableEnd property of the text view.
I have RelativeLayout and two TextView, one of which with background.
On image two baselines aligned, but I want to align baseline of one and background bottom of another.
Here is my xml code.
<RelativeLayout
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="#dimen/chat_room_item_height"
android:background="?attr/selectableItemBackground"
android:paddingEnd="16dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingStart="16dp"
>
<!-- other stuff -->
<TextView
android:id="#+id/text_view_unread_message_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_below="#+id/text_view_last_message_date"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:background="#drawable/chat_unread_message_count_background"
style="#style/ChatRoomUnreadMessageCountTextStyle"
tools:text="101"
/>
<TextView
android:id="#+id/text_view_last_message"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/text_view_title"
android:layout_toEndOf="#id/image_view_icon"
android:layout_toLeftOf="#id/text_view_unread_message_count"
android:layout_toRightOf="#id/image_view_icon"
android:layout_toStartOf="#id/text_view_unread_message_count"
android:ellipsize="end"
android:layout_alignBaseline="#+id/text_view_unread_message_count"
android:gravity="bottom"
android:maxLines="1"
tools:text="My life is a story book with many different chapters but I don’t let everyone read it."
style="#style/ChatRoomLastMessageTextStyle"
/>
</RelativeLayout>
I have tried wrap TextView with background to different ViewGrops, wrap both TextView to layout, no avail.
You can do a little trick, here we go:
Put the text_view_unread_message_count inside a some viewgroupo e.g. RelativeLayout and add a paddingBottom with using SP scaling (this is your space for manually align), something like this:
Obs.: You need to give a new ID to you TextView, this is a example ID's and size values can be changed.
<!-- sp scaling will change with font size -->
<RelativeLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:paddingBottom="10sp"
android:layout_marginLeft="8dp"
android:layout_marginStart="8dp"
android:layout_toEndOf="#id/image_view_icon"
android:layout_toLeftOf="#id/text_view_unread_message_count"
android:layout_toRightOf="#id/image_view_icon"
android:layout_toStartOf="#id/text_view_unread_message_count">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/chat_unread_message_count_background"
style="#style/ChatRoomUnreadMessageCountTextStyle"
tools:text="101"
/>
</RelativeLayout>
Put you locations definitions on parent and text definitions on textview. This should work.
You can set the required bottom margin programmatically.
val bottomToBaselineHeight = textViewLastMessage.height - textViewLastMessage.baseline
textViewUnreadMessageCount.margin(bottom = bottomToBaselineHeight)