I have a Layout which consists of a RelativeLayout, with a TableLayout holding 15 rows. Basically this is supposed to be a board game.
Each row has 15 RelativeLayout with a ImageView inside each of them.
The three first ImageViews match up evenly, but from the fourth one the ImageViews get a bit smaller height, leaving a small white border / line between the rows.
I have no Idea how to fix this, can anyone help?
As you can see from the image below, the three first squares are in full height, whilst the rest have a line underneath them.
Here is a small part of the code, all the rows are exactly the same so no need to paste all 15:
<?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">
<TableLayout
android:id="#+id/board"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="0dip"
android:layout_margin="0dip"
android:fitsSystemWindows="true">
<!-- 15 rows like this -->
<TableRow
android:layout_width="fill_parent"
android:layout_height="0dip"
android:layout_margin="0dip"
android:padding="0dip">
<!-- 15 relativeLayouts per Row -->
<RelativeLayout
android:id="#+id/boardTile_15_1"
android:layout_weight="1">
<!-- One ImageView per RelativeLayout -->
<ImageView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_margin="0dip"
android:padding="0dip"
android:src="#drawable/tile"
android:adjustViewBounds="true">
</ImageView>
</RelativeLayout>
<!-- End one RelativeLayout -->
</TableRow>
<!-- End one tableRow -->
Hard to say without testing, but a useful trick to 'debug' complex views like this, is adding background color to relevant subviews (i.e. RelativeLayouts containing your ImageViews), just to check who contains that padding.
You may also simplify as much as you can, for instance, you probably wouldn't need to wrap the ImageViews inside RelativeLayouts.
That said, my guess is that ImageViews need their scaleType attribute to be set, they'd look something like.-
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="fitXY"
android:src="#drawable/tile"
android:adjustViewBounds="true" />
There's no need to set padding/margin, as they're 0 by default, and remember that fill_parent is deprecated from API level 8.
Related
I am thinking to build an app which will have the same grid layout like in the picture, but I cant figure out what layout I should use.
GridView, or something like that?
It is possible using StaggeredGridView . Check out below repos on github
https://github.com/maurycyw/StaggeredGridView
https://github.com/chrisjenx/StaggeredGridView/tree/master/demo
Simple enough to do it with LinearLayout:
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<!-- Stack rows vertically -->
<LinearLayout android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<!-- First row, two items -->
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<!-- First item, 50% of width -->
<FooView android:id="#+id/foo1"
android:layout_width="0px"
android:layout_weight="1"
android:layout_height="wrap_content" >
<!-- Second item, 50% of width -->
<FooView android:id="#+id/foo2"
android:layout_width="0px"
android:layout_weight="1"
android:layout_height="wrap_content" >
</LinearLayout>
<!-- Next row, just one item -->
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<!-- Third item, 100% of width -->
<FooView android:id="#+id/foo2"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</LinearLayout>
<!-- And so on... -->
</LinearLayout>
</ScrollView>
Obviously, the exact nature of "FooView" is up to you, as are decorative borders, shadows, etc. In practice, you'd want to do this programatically, but this static xml layout shows you what you're after.
GridLayout also would work, but it's only available in 4.0 and above, unless you want to start using the compatibility library. Since LinearLayout will do the job, that's what I would use. RelativeLayout would probably also work, but I've never been able to get the damn thing to work, myself.
I'm not sure exactly what they use, but you can achieve the same effect with either a GridLayout or a ListView.
I'm trying to optimize the layouts in an Android app by flattening view hierarchies. Here's a particularly difficult one!
This layout has a main LinearLayout to hold the top and bottom rows (which are horizontal sub-LinearLayouts themselves). Each of the four items in the middle is a vertical RelativeLayout (to accommodate the ImageView and textView) spread out using layout_weights. Each row containing two items is ALSO a horizontal LinearLayout.
Needless to say, this layout is atrociously inefficient, leading to a lot of "Choreographer has skipped frames" messages when it is being drawn. I'd like to eliminate these nested Layouts, but AFAIK RelativeLayout is not helpful in equally spacing out the items in a row horizontally, and the two rows in the centre vertically. Also, I considered replacing the ImageView and TextView with a compound drawable, but I don't know how I can control the drawable's size.
Any help is appreciated!
Edit:
Here's a rough description of the Layout.
<!-- The top bar -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="80dip"
android:background="#drawable/some_image">
...
</LinearLayout>
<!-- Central Layout -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:weightSum="2"
android:orientation="vertical">
<!-- First Row -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0dp"
android:baselineAligned="false"
android:layout_marginTop="10dp"
android:layout_weight="1"
android:weightSum="2">
<!-- Item 1 -->
<RelativeLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical">
<!-- ImageView and TextView here -->
</RelativeLayout>
<!-- Item 2 -->
<RelativeLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical">
<!-- ImageView and TextView here -->
</RelativeLayout>
</LinearLayout>
<!-- End of first row layout -->
<!-- Second Row -->
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="0dp"
android:baselineAligned="false"
android:layout_marginTop="10dp"
android:layout_weight="1"
android:weightSum="2">
<!-- Item 3 -->
<RelativeLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical">
<!-- ImageView and TextView here -->
</RelativeLayout>
<!-- Item 4 -->
<RelativeLayout
android:layout_width="0dp"
android:layout_height="fill_parent"
android:layout_weight="1"
android:gravity="center_vertical">
<!-- ImageView and TextView here -->
</RelativeLayout>
</LinearLayout>
<!-- End of second row layout -->
</LinearLayout>
<!-- End of central layout -->
<!-- Bottom bar -->
<LinearLayout...>
....
</LinearLayout>
Your example looks a lot like the one shown in demo given by the Android team here:
http://developer.android.com/reference/android/widget/GridLayout.html
I am by no means super savvy with GridLayout (lots of trial and error before I get it working) but looking at what you have it should do the trick (esp if you would move all the buttons at the bottom to the top, and had them as an ActionBar).
Getting rid of the layout_weights will improve everything lots as every time those are used they are measure again and again.
The most optimum way of doing this would be to write your own custom ViewGroup. It's quite straightforward if you understand how android does its laying out.
See these slides by Romain Guy:
https://docs.google.com/leaf?id=0B_VKZCqEnHblNDdiY2UxODgtYWNhNS00MmU4LWE4NDMtZjQ1OWI5MDMxZTVh&sort=name&layout=list&num=50.
I want to have a relative layout inside another full-screen relative layout, occupying full width but 50% of its parent's height, preferably done with XML and not java code.
I have figured out how how to align parent's center, and how to fill up the width, but is there a way to get 50% of parent's height? What about 30%? 6.2834%?
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="??????????"
android:layout_centerInParent="true" >
The reason I'm trying to do percentage is that, if I specify it with "dip", while the object will remain the same size, the layout will look a lot different on different screen sizes (e.g. a phone and a tablet).
EDIT:
Thank you for all the answers about using LinearLayout and weighting. I have looked at that before, too. I feel I might have over-simplified the problem. Say I need something like this:
I suppose I could use complicated LinearLayout and weighting to outline the center square, then having the center square to fill_parent, like so:
But then what should I do with the other 3 squares (layouts)? Can I have another "layer" of LinearLayout for another square? Or should I divide up the whole screen into many, many small cells and having these sublayouts span over multiple cells (not sure if this is even possible)?
Try to use LinearLayout with weightSum
<LinearLayout 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"
android:weightSum="2"
android:gravity="center_vertical"
android:orientation="vertical" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#FF0000">
</RelativeLayout>
</LinearLayout>
If you don't absolutely need it nested in one RelativeLayout you can use weight in a LinearLayout as others have pointed out. I just added in an additional RelativeLayout above and below so you can use the rest of the screen if you are trying to. If not, just remove the other RelativeLayouts.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/ParentLinearLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="10" >
<RelativeLayout
android:id="#+id/RelativeLayoutTop"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2.5"
android:background="#color/torange" >
</RelativeLayout>
<RelativeLayout
android:id="#+id/RelativeLayoutMid"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="5"
android:background="#color/tpurple"
android:padding="8dp" >
<TextView
android:id="#+id/description"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="#string/describe"
android:textAppearance="?android:attr/textAppearanceLarge" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/RelativeLayoutBottom"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="2.5"
android:background="#color/torange" >
</RelativeLayout>
I usually go with a LinearLayout for this and set the weight to a certain percentage :
<?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:orientation="vertical">
<View
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="25"/>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="50">
</RelativeLayout>
<View
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="25"/>
</LinearLayout>
To your edit:
At some point you need to determine the layout. Start by taking the layout in groups. Look for patterns. In your simple explanation we have devised a way using a linearlayout to group 3 objects with one in the middle. With your new layout, could you group those items in any way?
Once you have simple layout patterns set, maybe add specific spacing that you are looking for by defining weights. Then you might want to add a relative layout and start anchoring views to specific views. Ask yourself do they overlap? Does one view always position on top of other views or on the sides. What defines the bounds of your views and then take it from there using linear layouts, weights, relative layouts, toLeftOf, toRightOf, bellow, above, margins, and padding.
Here is an example of what I mean by grouping like objects. It's by no means the best solutions but that all depends on how you define the positioning parameters.
Yellow = vertical linear layout
Green = horizontal linear layouts
You have 1 large vertical layout and inside two horizontal layouts with multiple objects inside of that. From there you can break it down into easier to manage portions on how to arrange and item within that layout. Now with relative layouts you could position items relative to another object, you could remove some of the work handled by the linear layouts but you will then be defining their distance relative to the other objects and might have to fiddle to get the layout to adjust properly on different screen sizes (reason to not use static positioning).
Maybe try using a LinearLayout with 3 layouts inside with android:layout_weight set to 1, 2, 1.
<?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:orientation="vertical" >
<RelativeLayout
android:background="#FF0000"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dip" >
</RelativeLayout>
<RelativeLayout
android:background="#00FF00"
android:layout_weight="2"
android:layout_width="match_parent"
android:layout_height="0dip" >
</RelativeLayout>
<RelativeLayout
android:background="#FF0000"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="0dip" >
</RelativeLayout>
</LinearLayout>
RelativeLayout does not support percentage of width and height for children. Use LinearLayout with android:layout_weight attribute.
I have a ScrollView on one of my screens. I want the right edge to have a shadow. I decided the easiest way to do this was to make the child of the ScrollView a RelativeLayout, and have two children of the RelativeLayout -- one being a LinearLayout that will house the layout of the screen, and the second View being the shadow.
Like so...
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scrollbars="none" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<!-- stuff -->
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:src="#drawable/shadow"
android:layout_alignParentRight="true"
/>
</RelativeLayout>
</ScrollView>
Unfortunately, this doesn't quite work. The ImageView is forcing its dimensions to be the size of the image file. It will not stretch vertically to be the height of the RelativeLayout. I've also tried "match_parent" to no avail. The image is a 9-patch.
Ideas?
Applying drawable content as the source of an ImageView somewhat carries with it an inherent requirement that you want the view to do what it can to accomodate the content without modifying the content itself very much. Typically, this is the behavior you would want out of an ImageView.
What you really want is the behavior you get by setting drawable content as the background of a view, for which you don't really need ImageView at all. A background is designed to simply stretch, fill, etc. to whatever size the view is. Also, since you are using RelativeLayout you can tell the view to match the bound of the view you are shadowing by adding an id and some extra layout_alignparameters.
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:id="#+id/content_layout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<!-- stuff -->
</LinearLayout>
<View
android:layout_width="11dp"
android:layout_height="fill_parent"
android:layout_alignParentRight="true"
android:layout_alignTop="#id/content_layout"
android:layout_alignBottom="#id/content_layout"
android:background="#drawable/shadow"
/>
</RelativeLayout>
try this
<ImageView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:background="#drawable/ic_launcher"
android:scaleType="fitXY"
android:layout_alignParentRight="true"
/>
here is what I get
and code id
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:fillViewport="true"
android:scrollbars="none" >
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<!-- stuff -->
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_alignParentRight="true"
android:background="#drawable/ic_launcher"
android:scaleType="fitXY" />
</RelativeLayout>
</ScrollView>
Your problem has nothing to do with the ImageView or 9-patch itself, but rather with the fact that you're wrapping everything in a ScrollView. A ScrollView will automatically force its children direct child to wrap its content, no matter whether you tell it to FILL_PARENT or MATCH_PARENT - both do exactly the same thing by the way; the only difference is the name, which reflects better the actual behaviour of the flag.
Fortunately ScrollView provides a way to force it to fill the viewport with a flag, which will make the behaviour pretty similar to setting FILL_PARENT to a regular view. Either add the attribute android:fillViewport or use setFillViewport() from code.
Edit: Just to be clear, you need to set that flag on the ScrollView. Also, if it's the ScrollView that should have the shadow, can you not send your 9-patch as background to it? I suppose it does depend on what your actual image looks like. Regarding you comment: yes, the RelativeLayout is flexible in terms of positioning and sizing children, but any child will still be bound to the size of its parent.
I do have the feeling that some of us may be working towards something different than what you have in mind. It would definitely help to clarify things with a simple drawing.
You wanted a Shadow towards the right of your image, Then use single layout with Horizontal Orientation, It's good that you have decide to use Relative Layout. Use
android:orientation="vertical"
inside this layout, add those two images. If you still have a doubt, give me those two images or sample images, i will give you the code
i'm new on Android plattform. I'm trying make a View that divide the screen in three sections. The first section should be 200dip high, the third section should be 50 dip high and the middle section should take the remaining place in the middle. Is there any way to implement it? I tried some ways but either it doesn't work or the app crashed.
Thanks for help
Patrik
Sure. Use a RelativeLayout which looks like this.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<!-- Defining the top view -->
<View android:layout_alignParentTop="true"
android:layout_height="200dip"
android:layout_width="fill_parent"
android:id="#+id/top_view"
android:background="#FFFF00"/>
<!-- Defining the bottom view -->
<View android:layout_alignParentBottom="true"
android:layout_height="50dip"
android:layout_width="fill_parent"
android:id="#+id/bottom_view"
android:background="#00FFFF"/>
<!-- Defining the view in between those views -->
<View android:layout_above="#id/bottom_view"
android:layout_below="#id/top_view"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#FF0000"/>
</RelativeLayout>
Provided comments in the code for you.
I usually achieve this by setting layout_height/width of fixed Views to specific values (e.g. android:layout_height="200dp") and setting android:layout_weight="1" with android:layout_height="wrap_content" for dynamic View. In that case LinearLayout should be used as containing ViewGroup.