I have a custom view/layout that need to be sized based on the contents of the children. The layout looks like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="100dp"
android:layout_height="64dp"
android:orientation="vertical">
<LinearLayout
android:id="#+id/rectangle"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#drawable/rectangle"
android:orientation="horizontal"
android:padding="5dp">
<ImageView
android:id="#+id/iconImageView"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center_vertical|left"
android:contentDescription="Icon"
android:src="#drawable/iconplaceholder"
android:scaleType="fitCenter"/>
<TextView
android:id="#+id/labelTextView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:textColor="#color/white"
android:gravity="center|left"
android:textSize="16dp"
android:text="Hello"/>
</LinearLayout>
<View
android:id="#+id/triangle"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_gravity="center_horizontal"
android:background="#drawable/triangle"
android:rotation="180"/>
</LinearLayout>
What I would like to do is:
List item
Allow the view to have a max width
Make sure that the entire text of #+id/labelTextView of the text view is visible in the view and allow it to grow taller if needed, but not get any wider than the max width.
If the text is really short, the view should just be as wide as needed
Set the size of the #+id/iconImageView from code and make sure that the parent view is resized accordingly
I guess I need to override onMeasure of my view, but please advice if this is the correct way. Also, how can I measure the size of a TextView given a set of constraints, like a max width?
I would think you would be able to set the layout_height for the parent to wrap_content. This way, it sets its view to be the size it needs to be depending on the sizes of the children inside it.
Related
I have a TextView and ImageView in a ListView row, positioned next to each other. However, the ImageView doesn't show up at all, and doesn't register clicks either. This is the XML code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView"
android:text="text"
android:layout_width="320dp"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_centerVertical="true"
android:padding="10dp" />
<ImageView
android:id="#+id/imageView"
android:clickable="true"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_centerVertical="true"
android:layout_toRightOf="#id/textView"
android:src="#drawable/ic_action"/>
</RelativeLayout>
The problem seems to lie in the layout_toRightOf line, if I remove it, the ImageView is shown, but in the wrong place. But I don't understand why it's causing a problem. What am I missing?
The issue is that the TextView is pushing the ImageView off the screen.
You can fix this using a LinearLayout and android:layout_weight
eg:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textView"
android:text="text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginTop="10dp"
android:layout_centerVertical="true"
android:padding="10dp" />
<ImageView
android:id="#+id/imageView"
android:clickable="true"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_centerVertical="true"
android:layout_toRightOf="#id/textView"
android:src="#drawable/ic_action"/>
</LinearLayout>
More info on the 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.
You need to use LinearLayout with weight.. if you set fixed width and the size of the phone is small, it will either stretch out of the screen.
//do linearlayout with orientation horizontal
<LinearLayout
...
orientation = "horizontal"
...
>
<TextView
....
android:layout_width="0dp"
android:layout_weight="1"
...
/>
<Button
....
android:layout_width="wrap_content"
...
/>
</LinearLayout>
Play with android:layout_weight, you will understand
I have a pretty simple RecyclerView within a DialogFragment
A single-line item is supposed to show an image, first and last name and some numbers. They are laid out with the help of layout_weight to equally share the available space.
For some reason, some of the items randomly seem to calculate the layout_weight wrong.
Note that in the editor preview, and after scrolling the problematic item out of view, the problem is fixed and the layout returns to normal.
As you can see in the image, in the first item (it's not always (just) the first) the image gets way too much space.
My layout is as follows;
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/dodger_blue"
android:orientation="horizontal"
android:padding="8dp">
<ImageView
android:id="#+id/iv_face"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"/>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2"
android:orientation="vertical">
<TextView
android:id="#+id/et_first_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLargeInverse"
android:textStyle="bold"/>
<TextView
android:id="#+id/et_surname"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMediumInverse"/>
</LinearLayout>
<TextView
android:id="#+id/et_id"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:gravity="center"
android:textAppearance="?android:attr/textAppearanceMediumInverse"/>
<TextView
android:id="#+id/et_place"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.8"
android:gravity="center|end"
android:textAppearance="?android:attr/textAppearanceLargeInverse"/>
</LinearLayout>
And my adapter;
https://gist.github.com/StefanDeBruijn/f032eac6619ac1b8420e352b883ea4dd
I suspect this is happening because of the large image being set in the image view. As you have set the height of the image as match_parent. To maintain the aspect ratio it is also expanding across the width.
Probably you should try adding this property to the in your xml file and fixing the height of the image.
android:scaleType="fitXY"
android:layout_height=100dp
Let me know if this fixes your issue.
I wonder if it is possible to have two items in a LinearLayout one wraps its content and the other fills the remaining horizontal space. I do this frequently in WPF (.NET) by specifying
HorizontalAlignment="Stretch".
For example:
<ImageView
android:layout_width="wrap_content"
android:layout_height="24dp"
android:background="#0000FF"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="24dp"
android:background="#FF0000"/>
When I do this the second ImageView fill the whole horizontal space as I expected. I tried to set both wrap_content and use gravity such as android:gravity="start" and android:gravity="fill_horizontal" for the second one it did not worked.
NOTE: I can achieve something similar by specifying weight attribute. But this is providing a division according to the percent value. This is not I want.
You can do this using the weight attribute itself. Try the following method
<ImageView
android:layout_width="wrap_content"
android:layout_height="24dp"
android:background="#0000FF"/>
<ImageView
android:layout_width="0dp"
android:layout_height="24dp"
android:layout_weight="1"
android:background="#FF0000"/>
include this in your horizontal linear layout
You need to use a Relative layout for this. Also you either need to specify a width for first image view or it should contain an image otherwise, how can the imageview wrap the content.
You can use like below :
<?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="match_parent" >
<ImageView
android:layout_alignParentLeft="true"
android:id="#+id/imgFirst"
android:layout_width="50dp"
android:layout_height="24dp"
android:background="#0000FF" />
<ImageView
android:layout_width="match_parent"
android:layout_height="24dp"
android:layout_alignParentRight="#+id/imgFirst"
android:layout_toRightOf="#+id/imgFirst"
android:background="#FF0000" />
</RelativeLayout>
I have two linear layouts inside a parent linear layout. all horizontal. I want all of l_child to show and part of r_child to show; while the rest of r_child will be off-screen to the right. How do I accomplish that?
<LinearLayout
android:orientation="horizontal" >
<LinearLayout
android:id="#+id/l_child"
android:orientation="horizontal" >
</LinearLayout>
<LinearLayout
android:id="#+id/r_child"
android:orientation="horizontal" >
</LinearLayout>
</LinearLayout>
Try giving the parent LinearLayout a negative right margin.
android:layout_marginRight="-50dp"
Other solution might be to put the parent LinearLayout inside a ScrollView, and set the widths of children layouts to the desired width. In this case, you'll be able to scroll the right layout back to the screen.
Layout weights are only for distributing layouts to fill a view, so no overflowing can be done this way.
Assigning layout_width with density independent pixels will result in varied success for different size devices.
So I believe you would have more success adding your layouts programmatically based on the screen size.
See this post for getting the screen width:
Get screen dimensions in pixels
Once you have the screen width, you can assign the inner-layout dimensions by pixels (with LinearLayout.LayoutParams), calculated as percentages of the screen width.
If you want the left layout to take up 80% of the screen, use .8*screen_width for the size, and if you want the right layout to then overflow by 20% of the screen, use .4*screen_width for that size.
Do you mean something like this
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_weight="1"
android:orientation="horizontal"
>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="70dp"
android:layout_gravity="center_horizontal|top">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:id="#+id/imageView1"
android:src="#drawable/ic_launcher"
/>
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:id="#+id/imageView2"
android:src="#drawable/ic_launcher"/>
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:id="#+id/imageView3"
android:src="#drawable/ic_launcher"/>
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="70dp"
android:layout_gravity="center_horizontal|top">
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:id="#+id/imageView1"
android:layout_marginRight="200dp"
android:src="#drawable/ic_launcher"/>
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:id="#+id/imageView2"
android:src="#drawable/ic_launcher"/>
<ImageView
android:layout_width="48dp"
android:layout_height="48dp"
android:id="#+id/imageView3"
android:src="#drawable/ic_launcher"/>
</LinearLayout>
</LinearLayout>
You can try using ViewPager, but I don't know if you can get the "bleeding canvas" effect that you're describing using that UI component.
EDIT: Maybe you can try using Gallery widget.
Is this what you're describing?
http://www.bangkokpost.com/media/content/20110915/309542.jpg
I have a PizzaOverview.
XML:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView android:layout_height="wrap_content" android:layout_width="fill_parent" android:text="" android:id="#+id/pizza_tv" android:gravity="center_horizontal" android:textSize="15pt"></TextView>
<ImageView android:layout_height="wrap_content" android:layout_width="wrap_content" android:id="#+id/pizza_iv" android:src="#drawable/icon" android:layout_gravity="center_horizontal"></ImageView>
<RatingBar android:layout_height="wrap_content" android:layout_width="wrap_content" android:id="#+id/pizza_rb" android:layout_gravity="center_horizontal"></RatingBar>
<TextView android:layout_height="wrap_content" android:text="" android:id="#+id/pizza_date" android:gravity="center|center_horizontal" android:layout_width="fill_parent"></TextView>
<RelativeLayout android:id="#+id/relativeLayout2" android:layout_width="fill_parent" android:layout_height="fill_parent">
<Button android:text="close" android:layout_height="wrap_content" android:id="#+id/pizza_bt" android:layout_alignParentBottom="true" android:layout_width="fill_parent"></Button>
</RelativeLayout>
</LinearLayout>
If the picture is too big the date is invisible.
add scroll view to your layout or fix the size of imageview
add the scroll view to your layout
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
>
<TextView android:layout_height="wrap_content" android:layout_width="fill_parent" android:text="" android:id="#+id/pizza_tv" android:gravity="center_horizontal" android:textSize="15pt"></TextView>
<ImageView android:layout_height="wrap_content" android:layout_width="wrap_content" android:id="#+id/pizza_iv" android:src="#drawable/icon" android:layout_gravity="center_horizontal"></ImageView>
<RatingBar android:layout_height="wrap_content" android:layout_width="wrap_content" android:id="#+id/pizza_rb" android:layout_gravity="center_horizontal"></RatingBar>
<TextView android:layout_height="wrap_content" android:text="" android:id="#+id/pizza_date" android:gravity="center|center_horizontal" android:layout_width="fill_parent"></TextView>
<RelativeLayout android:id="#+id/relativeLayout2" android:layout_width="fill_parent" android:layout_height="fill_parent">
<Button android:text="close" android:layout_height="wrap_content" android:id="#+id/pizza_bt" android:layout_alignParentBottom="true" android:layout_width="fill_parent"></Button>
</RelativeLayout>
</LinearLayout>
</ScrollView>
</LinearLayout>
Ensure that the images you supply to the activity are the correct resolution and size.
Also make sure that you have separate layouts for separate screen size categories.
Read this section of the android documentation for more details on layouts and managing different screen sizes. It tells you the basics you'll need.
You could place your image with the rating bar and the text below it in a RelativeLayout. Give a marginBottom to your RelativeLayout equal to the height of your Button. Then place your text, give it an id and add android:layout_alignParentBottom="true". Set the height of the image to fill_parent and add attribute android:layout:below="id_of_text".
You can as the other answer states make the screen scrollable. But if your content is dynamic (and depending on device it is arguable to say you content will ALWAYS by dynamic) you should make sure the that ImageView has it's bounds set correctly.
In the source code you have:
<ImageView android:layout_height="wrap_content" android:layout_width="wrap_content" android:id="#+id/pizza_iv" android:src="#drawable/icon" android:layout_gravity="center_horizontal"></ImageView>
You should instead have:
<ImageView android:layout_height="0dp"
android:weight="1"
android:layout_width="match_parent"
android:id="#+id/pizza_iv"
android:src="#drawable/icon"
android:layout_gravity="center_horizontal"
android:scaleType="centerInside"/>
The extra attribute of weight will make your view fill any available space along the orientation set in the bounding LinearLayout. This is dependant on the weight of other views along that orientation (as the other views have no weight value in this case it will fill all space up until the edge of your fixed views).
The extra attribute of scaleType="centerInside" will make your image sit in the center of the bound's you have suggested (which are the width of the screen and all available space vertically) without ever growing large enough to overlap the bounding container.
When using ImageView you should keep in mind that the ImageView is a bounding container for an Image. It can be as large or as small as possible but is only a mechanism for telling the UI where to place an image. The scaleType attribute is what you use to say how you want the image placing within this bounding countainer. Using "wrap_content" on an ImageView isn't effective and can lead to trouble later in the design (especially when considering different devices).