Separate image from AppCompatTextView - android

I have a Linear Layout with a list of six horizontal button in column. Each Button is defined as a AppCompactTextView since I need to place two images on it, as you can see in the following image:
What I need to do is separate the drawableStartCompat image (the one on the left) from the AppCompactTextView, without changing its position. I would like to keep it separated from the button. How can do it? I was thinking to wrap it with the button in a View but I do not know how to manage it. This is the code of one of the six element of the list:
<androidx.appcompat.widget.AppCompatTextView
android:id="#+id/view_top_up_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#android:color/transparent"
android:text="#string/placeholder"
android:textColor="#color/black"
app:drawableEndCompat="#drawable/ic_arrow_right_small_black"
app:drawableStartCompat="#drawable/ic_menu_charge" />

You can wrap the Imageview & TextView into any viewgroup you like & create one view like this, which gives you flexibility to maintain margin postion etc for your view:
<?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:gravity="center"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:id="#+id/leftImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:src="#drawable/ic_android" />
<TextView
android:id="#+id/tvTitle"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_weight="1"
android:padding="8dp"
android:text="Boost"
android:textSize="16sp"
android:textStyle="bold" />
<ImageView
android:id="#+id/rightImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:src="#drawable/ic_arrow_right" />
</LinearLayout>
</LinearLayout>
Output:
You can even go ahead & create a custom/compound view out of your layout.

Create custom button out of horizontal LinearLayout, which contains ImageView, Button and perhaps another ImageView for the image on the right.

Related

Wrap right-aligned view when there is no space

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.

How to make view at the end of textview even if the textview is so long?

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.

when adding views they go one below another even if width is wrap content

I have a Linear layout then programatically I'm adding some spinners and buttons and so on, but I have xml button Wrap content (width) and then on java I add spinner (or anything else) and it goes below this view even if both views are wrap content:
progBar = new ProgressBar(this);
pBarToca = new ProgressBar(this);
pBarToca.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
linToca = (LinearLayout) findViewById(R.id.tetoca);
linToca.addView(pBarToca);
and it's placed under the button of xml:
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" android:layout_marginTop="6dp"
android:id="#+id/tetoca">
<TextView style="#style/StylePartida"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/te_toca_jugar" />
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#A7E9A9" android:onClick="callJugar"
android:text="#string/jugar" />
</LinearLayout>
edit!!!!!!
I want textview on first line then on next line button + progressbar (for example)
You have android:orientation=vertical so the Views will be laid out starting at the top and going down.
If you want them to all be next to each other, remove that from your xml since the default orientation for a LinearLayout is horizontal. If you do this, you will obviously need to change the android:width to wrap_content for your TextView or else it will take up the entire screen.
After your comment, a RelativeLayout would work best here.
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView
style="#style/StylePartida"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/te_toca_jugar"
android:id="#+id/tvID" /> // give it an id
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:id="#+id/tetoca"
android:layout_below="#/id=tvID"> // place it below the TV
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#A7E9A9" android:onClick="callJugar"
android:text="#string/jugar" />
</LinearLayout>
</RelativeLayout>
Note the changes in the comments. Now when you add your progressbar to the LL, it should be next to the Button. You may need some changes but this should give you approximately what you want.
<LinearLayout android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:id="#+id/tetoca">
<TextView style="#style/StylePartida"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/te_toca_jugar"
android:text="#string/te_toca_jugar" />
<Button android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#A7E9A9" android:onClick="callJugar"
android:text="#string/jugar" />
</LinearLayout>
In your textView you are matching the parent
android:layout_width="match_parent"
This will cause the textview to take up the entire width of the parent view.
android:layout_width="wrap_content"
and
android:orientation="horizontal"
android:orientation="vertical" will cause the elements to be stacked.
If you are using "horizontal" it's important not to have a child element with width matching parent.
EDIT:
After OPs change to question:
I have used a textview, two buttons and listview to give you an idea of how you can format it. There are many ways to achieve the same thing, this is one suggestion.
The internal linearlayout has a horizontal orientation (by default).
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="te_toca_jugar"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#A7E9A9"
android:text="jugar"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#A7E9A9"
android:text="jugar2"/>
<ListView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/lv">
</ListView>
</LinearLayout>
</LinearLayout>

How to dynamically add a TextView/ImageView to a ListView item in Android

I am creating a chatting app in Android.
I was able to create the normal text chat list view with the following as the list item 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" >
<TextView
android:id="#+id/chat_msg_view"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"/>
<TextView
android:id="#+id/msg_send_time"
android:layout_width="250dp"
android:layout_height="20dp"
android:layout_below="#+id/chat_msg_view"
android:layout_margin="2dp"
android:paddingTop="2dp"
android:textColor="#android:color/holo_blue_dark" />
<TextView
android:id="#+id/msg_status"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_below="#+id/msg_send_time"
android:layout_margin="2dp"
android:paddingTop="2dp"
android:textColor="#android:color/holo_blue_dark" />
</RelativeLayout>
But now i am trying to send images as well via chat. So now i need to replace the first TextView in the above layout to ImageView if content being sent is IMAGE.
What is a good approach to do this.
There are lots of approaches you can use. If you are using a list view adapter you can use itemType to change the entire list item layout (good if you are changing the entire layout, but can be a bit complicated) or you can place an image view at the same location in your layout as the text view and show or hide which ever one you are using. I.E. If showing image, show the image view and hide the text view, if you are showing the text view, show the text and hide the image. Then you don't need to insert/remove views at run time, which is a little more complicated.
Your layout might look a bit like this...
<?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" >
<TextView
android:id="#+id/chat_msg_view"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"/>
<ImageView
android:id="#+id/chat_image_view"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:visibility="gone"/>
<TextView
android:id="#+id/msg_send_time"
android:layout_width="250dp"
android:layout_height="20dp"
android:layout_below="#+id/chat_msg_view"
android:layout_margin="2dp"
android:paddingTop="2dp"
android:textColor="#android:color/holo_blue_dark" />
<TextView
android:id="#+id/msg_status"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_below="#+id/msg_send_time"
android:layout_margin="2dp"
android:paddingTop="2dp"
android:textColor="#android:color/holo_blue_dark" />
</RelativeLayout>
Notice how chat_image_view is also aligned to parent left.. it will be on top of the text view, but it has visibility "gone" so you wont see it.
Hope this helps, good luck.

Unable to specify the alignComponent for an ImageButton

I'm trying to set my TextView to the left of an ImageButton, but I can't seems to find this option.
I was expecting to use something like android:layout_alignLeft, but this option is missing.
I've tried to google the issue, but couldn't find any relative results.
Without it my TextView overlaps the ImageButton and I want to avoid it.
UPDATE
The full xml code is too complex, but here is the important part of it:
<FrameLayout
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_alignParentLeft="true"
android:background="#color/white"
android:layout_marginLeft="8dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:layout_toLeftOf="#+id/frameLayoutBalanceClosed">
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/button_edit_nickname"
android:id="#+id/card_closed_control_editNickname" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/card_closed_description_nickname"
android:layout_margin="8dp" android:layout_gravity="left"/>
</FrameLayout>
I think what you need is a RelativeLayout. You can specify your TextView to the left of your ImageView with it's specifications. Your code would look something like this:
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<TextView
android:id="#+id/text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="#+id/imagebutton1" />
<ImageButton
android:id="#+id/imagebutton1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
The reason FrameLayout isn't working is because it's purpose is to overlay items on top of each other, which wouldn't work at all!
If that isn't what you're looking for, you could also use a TableLayout in which items are arranged in columns.

Categories

Resources