Android: How to apply LayoutParams to my RelativeLayout - android

I'm having difficult with this bit of code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
RelativeLayout layout = (RelativeLayout)findViewById(R.id.RelativeLayout1);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
I have my RelativeLayout1 in xml like this:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/ScrollView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/RelativeLayout1"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:paddingLeft="60dp"
android:paddingTop="53dp" >
But when I apply the scrollview, the fill_parent for RelativeLayout1 does not work as it should when it is not a child of scrollview. When it is not a child (i.e. I remove scrollview completely) then the relative layout covers the whole screen as I like it to. But when I put it inside scrollview, it only reaches the last element (a button) inside the relativelayout even though I use fill_parent.
So I am trying it programmatically to see if it makes a difference, but I can't seem to figure out how to apply my params variable to my layout one in the first bit of code. If you have any other ideas, do let me know as well.

You have forgotten to call the setter method layout.setLayoutParams(params).
To apply your created parameters you have to give them to the actual layout.
Be cautious with using fill_parent when the parent is a ScrollView. As the Scroll view adapts its size to its children.

I figured out how to solve my problem by adding a field to the scrollview and not doing this programmatically. In the ScrollView, I had to set the following:
android:fillViewport="true"

Add the attribute android:fillViewport="true" to your ScrollView if you want the RelativeLayout to fill up the ScrollView.
See Romain Guy's post about the same here: ScrollView's handy trick

Related

Compound layout

I want to create a custom layout to reduce redundancy in the code. Currently every layoutfile has about 30 Lines of code which are identical.
My goal was to create a custom layout/view which can hold in itself children.
<BaseLayout xmlns:...>
<!-- Normal Content -->
<Button />
<Label />
</BaseLayout>
While the above xml holds most of the content, the BaseLayout is in itself an xml containing other views and functionality:
<FrameLayout xmlns:...>
<LinearLayout><!-- contains the Header--></LinearLayout>
<LinearLayout><!-- INDIVIDUAL CONTENT HERE--></LinearLayout>
<FrameLayout><!-- contains the loading screen overlay --></FrameLayout>
</FrameLayout>
So all children from the above xml should be inserted into second linear-layout. I have already succeeded into doing so. But am confronted with layout problems (match parents does not match parents and only wraps)
My approach was extending the LinearLayout with following logic:
/**
* extracting all children and adding them to the inflated base-layout
*/
#Override
protected void onFinishInflate() {
super.onFinishInflate();
View view = LayoutInflater.from(getContext()).inflate(R.layout.base_layout, null);
LinearLayout linearLayout = (LinearLayout) view.findViewById(R.id.base_layout_children);
while(0 < getChildCount())
{
View child = getChildAt(0);
LinearLayout.MarginLayoutParams layoutParams = (MarginLayoutParams) child.getLayoutParams();
removeViewAt(0);
linearLayout.addView(child, layoutParams);
}
this.addView(view);
}
Is there a better, cleaner approach to capsule the xml and reuse a basis layout? How do I fix the match_parent issue?
While writing this post and thinking hard how to explain best, the solution for the match_parent issue became clear. Though the question remains if there is a better approach for the whole problem.
//Solution:
this.addView(view, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
//wrong:
this.addView(view);
Suppose you have two layout files. common_views.xml and layout_main.xml. You can include content of one layout file into another 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="match_parent"
>
<include
android:id="#+id/common"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
layout="#layout/common_views" />
<WebView
android:id="#+id/webView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="#+id/common"
>
</WebView>
</RelativeLayout>

RelativeLayout takes all its space, even though I've set its height to "wrap_content"

Background
I have a RelativeLayout inside a FrameLayout/RelativeLayout (doesn't matter to me), which should be at the bottom of the screen (like a toolbar), and should hold a few views in it.
Its height is set to "wrap_content" and so does its child-views.
The child-views of this layout are : A textView that is on the left, and a Horizontal LinearLayout on the right with a few buttons.
The problem
It seems that no matter what I do, the textview is causing the RelativeLayout to take the whole space, instead of just its children.
The code
Here's the minimal XML content that causes this problem. I've removed the extra stuff (LinearLayout and its children, and also some attributes that don't matter) since they don't cause this problem in case I remove the TextView:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FF000000" >
<!-- Here I've put some views that don't have any relation with the views below, so it doesn't have anything with do with the problem -->
<RelativeLayout
android:id="#+id/RelativeLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:background="#drawable/vertical_gradient_transparent_to_black" >
<!-- Here I've put a LinearLayout that doesn't cause the problem, so I've removed it for simplicity-->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
</RelativeLayout>
I've tried many possible attributes, and also tried adding additional layouts to try to "fool" the RelativeLayout, but none of those have succeeded.
The question
Why does it occur?
A working solution would be to use a Horizontal LinearLayout (with a weight for the TextView ) instead RelativeLayout , but I still want to know why can't I use a RelativeLayout, and why it occurs. Also how to fix it while still using RelativeLayout.
From the RelativeLayout doc:
Class Overview
A Layout where the positions of the children can be described in relation to each other or to the parent.
Note that you cannot have a circular dependency between the size of the RelativeLayout and the position of its children. For example, you cannot have a RelativeLayout whose height is set to WRAP_CONTENT and a child set to ALIGN_PARENT_BOTTOM
Class documentation
Which is exactly your case. RelativeLayout can not do that.
I have encountered the same issue before, this might be caused by android:layout_alignParentBottom attribute.Maybe you can find another way to achieve your desired effect. See this for more information.
This is some kind of Strange issue. Maybe someone else has the explanation.
I found it working when i removed the line
android:layout_alignParentBottom="true"/>
and it also worked when i tried some like this
<TextView
android:layout_width="match_parent"
android:layout_alignParentTop="true"
android:layout_height="wrap_content"/>

Move relative layout from AlignParentBottom to AlignParentTop

I'm doing this in Xamarin, so there will be slight deviations in the casing and names of methods.
I have a RelativeLayout that has ads and is placed at the bottom. Unfortunately, the ads block part of the playable map, so I'm attempting to move it to the top when the player moves near the bottom. I initialize the banner with the following code:
_banner = new RelativeLayout(this);
_lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
_lp.AddRule(LayoutRules.AlignParentBottom);
_lp.AddRule(LayoutRules.AlignParentLeft);
AddContentView(_banner, _lp);
I'm now attempting to move it to the top, but am failing. I've tried removing and re-adding it, but that does nothing.
var lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
((FrameLayout)(_banner.Parent)).RemoveView(_banner);
lp.AddRule(LayoutRules.AlignParentTop);
lp.AddRule(LayoutRules.AlignParentLeft);
AddContentView(_banner, lp);
I've also tried setting the LayoutParameters, but that throws an exception. What am I doing wrong?
Thank you.
-Nick
From your code I gather you are nesting a RelativeLayout (contains the ad) inside a FrameLayout. Your RelativeLayout only matches your parent in width, not height.
As such the RelativeLayout doesn't have the same size as your FrameLayout.
Your ad is thus touching both top and bottom of the RelativeLayout. And that RelativeLayout is always aligned to the top of the FrameLayout.
To solve this you have three options:
Make the RelativeLayout match the entire height of the FrameLayout and position your ad within that RelativeLayout.
Change the FrameLayout into a RelativeLayout, that way your alignParentBottom parameter will start working.
Use a 'layout_gravity' parameter on the RelativeLayout to tell the FrameLayout you want this View sent to the bottom.
Effectively your code is doing:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:alignParentBottom="true"
android:background="#FF0000"
android:layout_width="match_parent"
android:layout_height="240dp"
/>
</FrameLayout>
But for stuff to work you need to use android:layout_gravity which is a FrameLayout.LayoutParameter.
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_gravity="bottom"
android:background="#FF0000"
android:layout_width="match_parent"
android:layout_height="240dp"
/>
</FrameLayout>
Just paste the two pieces in a layout.xml and use the Android Designer to view the difference.

How to float/overlap a view in android?

I have many activities with a scrollview inside a tablelayout. However, it is necessary a small design change, so I have to put a black transparent view over the whole screen from the top to the bottom. Is it possible to do it in the tablelayout or the scrollview?
RelativeLayout allows for easy overlapping of views. You'll have to adjust the existing views in your app because it doesn't do anything automatically.
EDIT:
A quick way to do this would be to take your existing view (the ScrollView) that is already organized and put it in a top-level RelativeLayout. Then, all you have to do is add new view inside the RelativeLayout with the width and height both set to MATCH_PARENT. The result should be the black transparent view will be visible over the ScrollView.
I normally use FrameLayout to achieve any kind of 'layering' of views.
<FrameLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
//your existing layout
<View
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#33000000" />
</FrameLayout>
As DeeV said, you can probably use RelativeLayout in a similar way, but you might have to set additional attributes on its children to achieve this.

Problem building layout programmatically

I am building something like a ListView, but I'm rolling my own because I want to do some custom stuff and have more control than using ArrayAdapters.
So I've defined part of my layout in XML, including one LinerLayout inside a ScrollView. My goal is to bind to that Linearlayout in code, then insert additional RelativeLayouts inside the LinearLayout using no XML, just code.
Here is my XML:
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/ListScroll"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:id="#+id/ListHolder"
android:layout_height="400px"
android:background="#323232"
>
<!--Here is where I want the RelativeLayouts to go... -->
</LinearLayout>
</ScrollView>
Then in code, I'm trying to add RelativeLayouts, each 50px in height, to the LinearLayout, the one above that has a height of 400px.
//The parent container - is defined above in XML.
itemContainer = new LinearLayout(context);
itemContainer = (LinearLayout)findViewById(R.id.ListHolder);
Layouts = new ArrayList<RelativeLayout>();
Layouts = LoadWithRelativeLayouts();
for(RelativeLayout listItem: Layouts){
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FILL_PARENT, 40);
listItem.setLayoutParams(params);
itemContainer.addView(listItem);
}
Each one of the layouts in the array has a text view in it that says "Test". When I step through the code, there are 10 elements in the array, and all of the textviews are there, so I would expect to see the 400px LinearLayout filled with 10 Relative layouts one after another, each with 50px height (and fill_parent width) reading "Test" - but all I see is one, as if only one got added, or they are all positioned on top of one another.
Getting screenshot now...
When you add something to a layout, you have to use layout params of that kind. So as you're adding to a LinearLayout, you should use LinearLayout.LayoutParams.
Then you'll probably also need to set your LinearLayout orientation to vertical, because right now the items you don't see are all in a row offscreen at the right :)
Try adding android:orientation="vertical" to the LinearLayout holding the RelativeLayouts.

Categories

Resources