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"/>
Related
This question is in a way a continuation of my last question.
My problem now is pretty much the same, except that instead of separating the image and text in differend views (namely ImageView and TextView) I learned I can use the attribute android:drawableLeft to set an image "for" my text (the suggestion was pointed to me by Eclipse with a warning icon on the LinearLayout line).
I thought the only difference would be that instead of setting the ImageView with setImageResource() method I would simply set the TextView's drawableLeft attributed with the setCompoundDrawablesWithIntrinsicBounds() method. Instead, when I made the change, I was taken back to my original issue: the text aligns with the top edge of the view rather than the center.
This is what my TextView looks like:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<TextView
android:id="#+id/account_login"
android:layout_marginTop="10dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableLeft="#drawable/pm_gmail"
android:drawablePadding="8dp"
android:text="example#gmail.com"
android:paddingLeft="16dp"
android:layout_gravity="left|center_vertical" />
<View
android:layout_width="fill_parent"
android:layout_height="1dip"
android:layout_centerVertical="true"
android:layout_below="#id/account_login"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="5dp"
android:background="#DDDDDD" />
</RelativeLayout>
The second View is just a separator.
... and this is what the layout looks like after setting the above mentioned attributes:
(I don't have enough reputation to post images yet, so here's the link to it)
(Just to be clear, this is only a static example. My text and image are both set dynamically in the code at runtime).
Any help is greatly appreciated.
Change android:layout_gravity="left|center_vertical" to android:gravity="center_vertical".
layout_gravity is for positioning a View inside a container (layout), while gravity is referred to
the View contents (that is, in this case, the text inside the TextView).
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 imagine this should be a fairly easy one to answer, if you understand XML Layouts better than I do that is. I don't seem to get what I was thinking I should when using the match_parent layout_height.
I have a LinearLayout root element with android:orientation="vertical". Inside this LinearLayout I want three elements:
- TextView
- ListView
- TextView
For both the TextViews I set android:layout_height="wrap_content" so that they will be only as tall as is necessary to display their contents. The thing is, I want the one TextView to sit at the top of the form, the other one to sit at the bottom of the form while the ListView fills up whatever space is available on the form. So here is what my xml layout looks like:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="Top TextView" />
<ListView
android:id="#+id/listView_Species"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="Bottom TextView" />
But it doesn't work. Here's what I get. I've selected the ListView so that it will be highlighted. Notice how it extends all the way to the bottom of the form, pushing the bottom TextView off the form.
When I change the layout_height property of the ListView to some fixed value, like 180dp, this is what the form looks like. I'm just posting this to prove that the bottom TextView is there but I still don't know how to get it to be fixed to the bottom of the screen while the ListView takes up whatever space remains, but in between the two TextViews.
Thanks in advance.
While the other answers try to fix your problem (which they don't actually--they suggest you do something that looks similar but may or may not look good on different devices), no one has filled in the gaps in your knowledge of LinearLayouts and match_parent. And these gaps are very common--Google's documentation is still far below stellar.
First, how do Views work within a LinearLayout? Let's go through the process of drawing a LinearLayout, using orientation="vertical" for simplicity.
Examine the height of the first child of the LinearLayout (LL for short). If the height is match_parent or fill_parent (old name for the same thing) then the height of the View is stretched to fill the entire viewing area. If the height is wrap_content, then measure the vertical space the View takes and use that space for the View. If the height is a non-zero number, use exactly that many pixels for the View's height (may clip if too small). If the height is 0 see below.
Put the next view below the view in 1. Check its height and act accordingly.
Continue for all the Views. If a View is pushed off the bottom, go ahead and stop calculating because no one will see it or any succeeding Views (assuming no ScrollView).
If the height of a View is 0, check it's gravity. This requires a second pass, storing the gravity of all the views and then allocating their heights proportionally. As you can guess, the second pass doubles the time layout takes, which isn't significant for simple layouts.
Explanation of your example: The first child of the LL (the first TextView) is measured and takes a certain amount of pixels. Then your ListView takes all the remaining space (via match_parent). And then your second TextView is not drawn at all as it's off the bottom of the screen. Which is pretty much what you observed, but now you understand why.
Solution: Use RelativeLayout. Works perfectly in this case.
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/top_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:textSize="30sp"
android:text="Top TextView" />
<TextView
android:id="#+id/bottom_tv"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:textSize="30sp"
android:text="Bottom TextView" />
<ListView
android:id="#+id/listView_Species"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="#id/top_tv"
android:layout_above="#id/bottom_tv"
/>
</RelativeLayout>
The RelativeLayout tells the layout inflater to draw the first TextView at the top, then draw the second TextView at the bottom, and then fill the rest of the space with your ListView. I believe this is exactly what you want.
Welcome to Android. You'll be using this pattern a LOT!
Change the ListView height to 0dp and add weight=1
i.e.:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="Top TextView" />
<ListView
android:id="#+id/listView_Species"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="30sp"
android:text="Bottom TextView" />
use android:layout_weight to define weights to your widgets inside the outermost layout. Declare their height as 0dp and then define android:layout_weight to each one of them .
Total weigh sum of the three of them should be 1. According to your need you can deine 0.1 weight to both top and bottom TextView's and define 0.8 to ListView.
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight = "0.1"
android:textSize="30sp"
android:text="Top TextView" />
<ListView
android:id="#+id/listView_Species"
android:layout_width="match_parent"
android:layout_weight = "0.8"
android:layout_height="0dp" />
<TextView
android:layout_width="match_parent"
android:layout_height="0dp"
android:textSize="30sp"
android:layout_weight = "0.1"
android:text="Bottom TextView" />
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.
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.