I have a n app widget that is pretty much working, with one quirk. I've got a LinearLayout in the widget, and I can add rows of my data to it just fine. There doesn't seem to be any obvious way for me to tell how big the linear layout is and if a given row will fit, so I just add the entire data set (since it isn't very large). The text in my layout gets cropped at the bottom, which is what I'd expect. However, the ImageView next to it is not being cropped, but is instead being scaled. It, frankly, looks goofy.
If there's a way for me to tell if a row will fit in my LinearLayout, that would be great. If there's a way I can tell it to just crop my image, that would be fine too. This is what the cropping looks like.
The layout for the rows I'm adding (if there's a goof here, it's probably from the anonymization I applied):
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/checkbox"
android:layout_width="28sp"
android:layout_height="28sp"
android:src="#drawable/check_off"
android:layout_marginLeft="5dp"
android:layout_marginTop="1dp"
android:layout_alignParentLeft="true"/>
<TextView
android:id="#+id/textview"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textSize="16sp"
android:minHeight="28sp"
android:paddingLeft="5dp"
android:layout_centerVertical="true"
android:layout_alignWithParentIfMissing="true"
android:layout_toRightOf="#id/checkbox"/>
</RelativeLayout>
EDIT: The container for the rows is just a simple LinearLayout:
<LinearLayout
android:id="#+id/list_items"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:layout_above="#id/logo"
android:layout_marginBottom="4dp"
android:padding="1dp"
android:orientation="vertical"
android:background="#drawable/widget_background"/>
Try adding a scaletype to your ImageView:
android:scaleType="centerCrop"
or
android:scaleType="fitCenter"
or any of the other options listed here:
http://developer.android.com/reference/android/widget/ImageView.ScaleType.html
It turns out that giving the RelativeLayout that corresponds to the row a specific height (30sp, for this layout) instead of "wrap_content" fixed the problem. The image now crops correctly.
Related
I have a TextView whose width should not exceed the ImageView above it. Both image and text are downloaded from server and I don't know their dimensions (can't make assumptions either). I went through the logic to wrap the text content using this SO post.
Here is my layout XML
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/parentLL"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout android:orientation="vertical"
android:id="#+id/LL1"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/image1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:width="0dp"
android:text="This is a string whose width may or may not be more than the image downloaded" />
</LinearLayout>
<TextView android:background="#android:color/holo_red_dark"
android:id="#+id/text2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:text="Second Text"/>
</LinearLayout>
With this code, the TextView at the end (text2) does not even show up. There are 2 solutions to this issue :
Apply android:maxLines="5" to the text1. Problem with this approach is that Text1 view would always be 5 lines high (I understand 'lines' is not a unit of height, but that's what I see visually). So if the text content is just one word, there would be a big white space below. And then text2 shows up.
Change topmost linear layout (parentLL) to RelativeLayout. text2 can then be used with alignBelow=LL1. This works as expected. But I cannot migrate the topmost view to RelativeLayout, because this view is from a library not in my control. I can only modify LL1 and it's children. Due to my code, other views below (like text2) are suffering (by not showing up).
There is a third approach for setting the textview as a compound drawable on ImageView. I guess that might work (haven't tested), but my requirement is to show the TextView if image download has failed (which can be detected only after a while). So I need to have a TextView. Also, my LinearLayout LL1 can have other children too.
I would request for some help understanding :
Why is my code not showing up the content below the textview 'text1'? With width=0 on textview it seems to set the height of the parent to be match_parent.
How is RelativeLayout able to handle this smoothly ? Can I replicate any of that behavior in TextView's onMeasure ? Assume I have callbacks to detect image has been downloaded, and I can get image width also.
I think what you are running into is a conflict of setting the width and height but not setting the layout weight, which is a key factor in how Linear Layouts work. If you add one more vertical LinearLayout in there and then move #id/text2 into it, you should be set. You'll need something like the following (obviously modified to your specs, this was just a quick test). Note my use of android:layout_weight,
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="#+id/textView3" />
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="#+id/textView2" />
</LinearLayout>
</LinearLayout>
Which splits the screen in half vertically as shown in this picture,
Photo of resulting layout
I had to wrap the TextView in a RelativeLayout, which was wrapped by a LinearLayout. Not happy with this solution, but this is the only way for now.
I am writing an Android game. In the level selection activity's layout file, I want to layout the levels' buttons (They are actually ImageViews) like this:
x x x
x x x
And each level button has a TextView, with that level's name as the text, below it (Let's call these two views together as a "level choice"). I used a lot of LinearLayouts to do this. Here is the code for a level choice:
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
android:layout_weight="1">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/angles"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/angles_level"
android:textSize="#dimen/level_text_size"/>
</LinearLayout>
As you can see, the two views' height and width are all wrap_content. But when I look at the designer, the text view doesn't show up.When I select the text view in the component tree, it shows where the text view is:
P.S. The picture isn't showing all six levels because I haven't made them yet.
As you can see, the text view is right at the bottom! When I select the ImageView, it shows that it is occupying all the space of its parent!
I don't know why this is happening, my image is certainly a square! Can you explain why this is happening and how do I fix it?
If you need my whole layout code, feel free to tell me in the comments.
For me, the best solution is to position and size it properly by code (where you have total control) instead of xml.
Anyway, i think your problem can be solved by setting ImageViews ScaleType
imageView1.setScaleType(ScaleType.FIT_START);
By XML:
android:scaleType="fit_start"
Hope this helps.
I use background color for textview when I'm studying the layout.
If you use wrap content in both dimension for TextView, that is invisible since you did not write any text inside it. wrap content means that the view take the minimum space. And no text means 0px; try to set ImageView and TextView with layout_weight 1 and layout_height 0dp. In this way both view take half of space of parent layout
Because right now, your LinearLayout doesn't know how to distribute the ratio of its children. And in fact, your imageview's wrap content already
consumes the whole space.
So, LinearLayout says "Sorry TextView, you have no space left".
Use layout_weight to both of the children.
I guess you want to have your picture twice the size of your text.
2:1
That is,
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:gravity="center_horizontal"
android:layout_weight="1">
<ImageView
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight=2
android:src="#drawable/angles"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight=1
android:text="#string/angles_level"
android:textSize="#dimen/level_text_size"/>
</LinearLayout>
I just realized that I posted a question about ImageViews leaving out too much whitespace:
LinearLayout leaving out too much white space. Why?
I think this is the same as that problem. So I tried setting adjustViewBounds to true in the xml. And it works! Now the image view look like this:
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:src="#drawable/parallel_lines"/>
You can use relative layout
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/angles"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/angles_level"
android:textSize="#dimen/level_text_size"/>
</RelativeLayout>
or simple you can set background of textview to that image by putting this
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/angles_level"
android:background="#drawable/angles"
android:textSize="#dimen/level_text_size"/>
How to show a vertical line on the background, such as the one highlighted in blue on the image below?
In this example, I have a ListView with ImageView elements (and TextView, but it is not related to the line), and I want a vertical line on the background of these items to feel like they are "connected" to each one.
And also, note that the vertical line does not fill all the background.
The vertical line is on the left, and it is not equal for the all cases. Sometimes it fills all the row height (in most of ListView rows) and sometimes it just fills the half of row height (in the last item of the ListView and outside of the ListView, on the top, where we can see the big ImageView with the star icon).
Updated
I tried the suggestion proposed by Hellboy, and it almost work perfectly. I modified the proposed code for my case:
<RelativeLayout
android:layout_width="40dp"
android:layout_height="match_parent"
android:gravity="center"
android:layout_marginLeft="15dp">
<View
android:layout_width="4dp"
android:layout_height="match_parent"
android:background="#3399CC"
android:gravity="center"
android:layout_centerHorizontal="true"/>
<ImageView
android:id="#+id/user_image"
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginTop="10dp"
android:layout_marginBottom="10dp"
android:gravity="center"
android:background="#android:color/holo_blue_light" >
</ImageView>
</RelativeLayout>
the RelativeLayout with the width="40dp" (the same as the original ImageView I was working with), height="match_parent (the same as he said), gravity="center" (to let them in the center of the row height) and layout_marginLeft="15dp" (to let a space to the left margin). In the ImageView, I added marginTop="10dp" and marginBottom="10dp", and with it, the blue vertical line appears. But I have other elements in the same row, so I have a parent layout (a linear layout). My parent layout is:
<?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="match_parent"
android:orientation="horizontal"
android:gravity="center"
android:id="#+id/linearlayoutservicerow">
So, this parent layout above, has the described RelativeLayout and other LinearLayout with the other row elements. But the code results in flattened images. Why does this happen?! It seems like the RelativeLayout consider its height as the ImageView height (40dp) and does consider its marginTop and marginBottom, and with this the image is flattened.
Waiting more answers to this problem. I'll try another alternatives.
You can replace your ImageView with something like this:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
android:layout_width="4dp"
android:layout_height="match_parent"
android:background="#color/navy_blue"
android:layout_centerHorizontal="true"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="#drawable/image"/>
</RelativeLayout>
and of course in your first and last element you need to manipulate the height of the View and align it to Top or Bottom
I got it.
I've persisted in trying to fix the problem of the Updated section of my question (based on the solution initially proposed by #Hellboy) and I got results! So, how I achieved an answer to my own question, I decided to put as an answer.
The first step was to configure the XML file such as the code below.
Part of the final XML corresponding to the row layout:
<?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="match_parent"
android:orientation="horizontal"
android:gravity="center"
android:id="#+id/linearlayoutservicerow">
<RelativeLayout
android:layout_width="40dp"
android:layout_height="match_parent"
android:gravity="center"
android:layout_marginLeft="15dp">
<View
android:layout_width="4dp"
android:id="#+id/verticallineview"
android:layout_height="match_parent"
android:background="#3399CC"
android:gravity="center"
android:layout_centerHorizontal="true"/>
<RelativeLayout
android:layout_width="40dp"
android:layout_height="match_parent"
android:gravity="center"
android:paddingBottom="10dp"
android:paddingTop="10dp">
<ImageView
android:id="#+id/user_image"
android:layout_width="40dp"
android:layout_height="40dp"
android:gravity="center"
android:background="#android:color/holo_blue_light" >
</ImageView>
</RelativeLayout>
</RelativeLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/layoutotherrowelements">
</LinearLayout>
</LinearLayout>
Explaining the XML:
Here we have the parent layout (linearlayoutservicerow) and inside it: a RelativeLayout (proposed by #HellBoym, with the structured discussed in the final of my question) and the LinearLayout to other elements of the row (layoutotherrowelements). Summarizing... What I modified?
The initial code resulted in flattened images because the RelativeLayout (parent) did not consider the ImageView marginTop and marginBottom, so the image was flattened vertically. (And if we let without margin, the RelativeLayout would mantain the same size and the vertical line would not appear on the top and on the bottom of image.) We must have a space between the ImageView and the RelativeLayout initially proposed, in order to show the line, but if it does not recognize the margin, how to create this space?
I just "encapsulated" the ImageView in another RelativeLayout (inside that parent RelativeLayout), and changed the margin parameters of the ImageView to padding parameters of this capsule RelativeLayout.
The problem of the last row
It results in the layout with a line background, but we still have the problem of the last row. In fact, this row is different, and in this case, it must have its height modified to not have the same parent's height. I decided to put at least, the ImageView's height and it worked! Remember to convert the value in dp to pixel, because the function getLayoutParams has all parameters expressed in pixels.
So, in the Adapter, we put the following code:
if(position==(getCount()-1)){
View my_line = (View)
row.findViewById(R.id.verticallineview);
//40dp, this is the ImageView height
int dpsize = 40;
//convert the height in dp unit to pixel (because the parameter is in px)
int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dpsize, context.getResources().getDisplayMetrics());
my_line.getLayoutParams().height = px;
}
And that is it!!!
It is worth mentioning that #dinesh sharma proposed other interesting alternative using 9-patch, that I will try later.
I did not want to use image as background (that is why I started asking about drawable), because my final goal was to improve this solution to make all dynamic (including the vertical line color), and I believe with image I could not achieve it. But in my original question I did not mention that, so if I have success with this other approach, I will accept it as correct answer.
Thanks for all your help! In my current solution I used the #Hellboy's clue of using a RelativeLayout and a View, and the #dinesh sharma's clue to verify if it is the last row of the ListView. I hope this answer and the others helps more people with similar problems.
You can use transparent 9-patch image as a background for you list view.
For creating nine-patch image please follow this:
http://developer.android.com/tools/help/draw9patch.html
Now verified answer
your image in item layout:
<RelativeLayout
android:id="#+id/rl"
android:layout_width="60dp"
android:layout_height="60dp"
android:background="#drawable/m"
android:paddingBottom="10dp"
android:paddingTop="10dp" >
<ImageView
android:id="#+id/grid_item_image"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_centerInParent="true"
android:src="#drawable/ic_launcher" />
</RelativeLayout>
three bg nine patch images for drawable
Handling in Adapter:
if(position==0)
holder.rl.setBackgroundResource(R.drawable.b);
if(position==(getCount()-1))
holder.rl.setBackgroundResource(R.drawable.t);
Finaly got output:
I'm getting two differents behavior for a ListActivity row. Eclipse Graphical Layout show the right behavior, but at runtime, on the device, the layout:weight doesn't seem to work properly and the Textview is resized to the minimum width, depending on the text property.
This is how I had setup the layout.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="60dp"
android:background="#color/defaultBg"
android:orientation="horizontal">
<ImageButton
android:id="#+id/myButton"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_marginLeft="5dp"
android:layout_weight="2"
android:src="#drawable/ic_launcher"/>
<TextView
android:id="#+id/myText"
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_margin="5dp"
android:background="#2288EE"
android:layout_weight="6" android:text="Hello" android:textColor="#android:color/white"/>
</LinearLayout>
EDIT: I just found that the LinearLayout doesn't fill the listRow width. I'm still trying to find how to solve
Any help will be very appreciated.
I fix the issue myself. The problem wasn't in the table row layout posted above. The problem was in the android:layout_width of the parent ListView which was set to 'wrap_content' instead of 'fill_parent'.
Thanks to everyone who offered his contribute!
In your LinearLayout put android:weightSum="8". It should do the trick, on my device works fine.
Try adding android:scaleType="fitCenter" to your ImageButton. If I'm not mistaken, your source Drawable is too big, therefore making the ImageButton take too much horizontal space.
So it's possible to align the top, bottom, left, and right of one view with another so that their edges are flush with each other. However, I've been wondering if it's possible to align the centers of two views of different sizes. My situation occurs when I have an ImageView side by side with a TextView, like this: [ImageView] [TextView]. The ImageView is bit taller than the TextView and so what I do is add padding/margins to the bottom of TextView to get it align and look like the ImageView and TextView horizontal centers are aligned. Problem is, when this view is displayed on larger tablet screens, the padding and margins don't work out right and the TextView doesn't look aligned with the ImageView. I'm sure there is an easy fix to allow this to always work out, so could someone provide me with some insights? Thanks!
This is how I did for a listview row:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FFFFFF"
android:padding="5dp"
android:gravity="center_vertical">
<TextView android:id="#+id/questionItemTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:textSize="20sp"
android:textColor="#000000"
android:gravity="center_vertical"/>
<ImageView android:id="#+id/questionViewed"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/eye"
android:layout_marginLeft="5dp" />
<ImageView android:id="#+id/questionAnswered"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/check"
android:layout_marginLeft="5dp" />
</LinearLayout>
Use weightSum rather than padding in dips or pxs, that will make your layout look fine regardless of the size of the user's device.
or you could use gravity as well.
Or you can create a second xml file and insert that one into your res/xlarge file, the phone will pick which xml to read.