Change margins programmatically doesn't work as expected - android

I have a GUI where Initially margins of innerLayout are 0,10,0,100 and in my intention hideinfoarea() should remove the infoLayout and change the margins in 0, 10,0,10 and showInfoarea() should restore the initial margins and show infoLayout again.
Unfortunately when I set these margins some Layout become not well shown, for example the title is too close to mainLayout, and a piece of image will be covered by infoLayout when I re-enable it.
despite in my test with layout editor the margins are perfect.
In adition when I invoke showInfoarea() why the layout margins aren't restored to the original conditions, if I simply reverse the operation of hideInfoarea()?
Here my code
RelativeLayout mainLayout;
LinearLayout innerLayout;
public void hideInfoarea(){
mainLayout = (RelativeLayout) findViewById(R.id.mainContainer);
innerLayout = (LinearLayout) findViewById(R.id.innerLayout);
mainContainer.removeView(infoLayout);
//adjust margins
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) innerLayout.getLayoutParams();
params.setMargins(0, 10, 0, 10);
innerLayout.setLayoutParams(params);
}
public void showInfoarea(){
mainLayout = (RelativeLayout) findViewById(R.id.mainContainer);
innerLayout = (LinearLayout) findViewById(R.id.innerLayout);
mainContainer.addView(infoLayout);
//adjust margins
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) innerLayout.getLayoutParams();
params.setMargins(0, 10, 0, 100);
innerLayout.setLayoutParams(params);
}
Here the XML
<!-- The main content view -->
<RelativeLayout
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"
tools:context=".MainActivity"
android:padding="5dp"
android:gravity="fill_horizontal|fill_vertical"
android:background="#color/Platinum"
android:id="#+id/mainLayout">
<TextView
android:id="#+id/txtTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:text="Sample"
android:textSize="12dp"
android:layout_marginBottom="10dp"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:id="#+id/innerlayout"
android:layout_marginTop="10dp"
android:layout_marginBottom="100dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:id="#+id/imageView"
android:scaleType="fitXY"
android:src="#drawable/rectangle"
android:layout_marginBottom="100dp"
android:layout_marginTop="10dp"/>
</LinearLayout>
<LinearLayout
android:layout_width="400dp"
android:layout_height="100dp"
android:layout_alignParentBottom="true"
android:background="#drawable/background_label_mm"
android:layout_centerHorizontal="true"
android:orientation="vertical"
android:id="#+id/infoLayout"
android:layout_margin="5dp">
</LinearLayout>
</RelativeLayout>
<!-- The navigation drawer -->
<ListView
android:id="#+id/drawer"
android:layout_width="320dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#F3F3F4"
android:choiceMode="singleChoice"
android:divider="#android:color/transparent"
android:dividerHeight="0dp"/>
</android.support.v4.widget.DrawerLayout>

Be carefull, as you can read one the Reference: setMargins(int left, int top, int right, int bottom) method use px and your layout use dp. You have to do a conversion like:
// where "dp" is your value dip
int px = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
(float) dp, getResources().getDisplayMetrics());
// then set your margins
params.setMargins(0, px, 0, px);
See this answer: What is the correct way to specify dimensions in DIP from Java code? and the reverse one: Converting pixels to dp.
Also, you can read another thing one the Reference:
Sets the margins, in pixels. A call to requestLayout() needs to be done so that the new margins are taken into account.
Hope this helps.

Related

How to place views equidistant horizontally in relative layout?

How to place views equidistant horizontally in relative layout?
I want to place views in relative layout occupying equal space according to the number of views added, similar to weight in Linear Layout
Layout I tried: (For three views)
<?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">
<!--<View
android:id="#+id/root"
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_centerHorizontal="true"
android:layout_margin="16dp"
android:background="#android:color/holo_blue_bright"/>-->
<RelativeLayout
android:id="#+id/left"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true">
<View
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_centerHorizontal="true"
android:layout_margin="16dp"
android:background="#android:color/holo_blue_bright"/>
</RelativeLayout>
<RelativeLayout
android:id="#+id/middle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="#id/left">
<View
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_centerHorizontal="true"
android:layout_margin="16dp"
android:background="#android:color/holo_blue_bright"/>
</RelativeLayout>
<RelativeLayout
android:id="#+id/right"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="#id/middle"
android:layout_alignParentEnd="true">
<View
android:layout_width="64dp"
android:layout_height="64dp"
android:layout_centerHorizontal="true"
android:layout_margin="16dp"
android:background="#android:color/holo_blue_bright"/>
</RelativeLayout>
</RelativeLayout>
Problem with the above layout is that the first two views are like wrap_content and the third one occupies all remaining space. How to make each view occupy one-third of horizontal space?
Note:
1. Kindly provide solution only in relative layout, not in linear layout or constraint layout.
2. The solution required should not be nested with Linear or other layouts. (Want flat layout)
If you want to stick with the relative layout you can do like this, get the the screen width like this.(need to get the pixel value)
private int Screendp(){
DisplayMetrics dm = new DisplayMetrics();
WindowManager windowManager = (WindowManager) this.getSystemService(WINDOW_SERVICE);
windowManager.getDefaultDisplay().getMetrics(dm);
int widthInDP = Math.round(dm.widthPixels / dm.density);
return widthInDP;
}
this is how we can convert dp to px
public int dpToPx(int dp) {
float density = this.getResources()
.getDisplayMetrics()
.density;
return Math.round((float) dp * density);
}
So in your activity set llayoutparams for each and every child views like below,
parent= findViewById(R.id.parent);
left= findViewById(R.id.left );
middle= findViewById(R.id.middle);
right= findViewById(R.id.right );
RelativeLayout.LayoutParams leftparams = new RelativeLayout.LayoutParams( dpToPx(64), dpToPx(64));
leftparams.leftMargin= 0;
left.setLayoutParams(leftparams);
RelativeLayout.LayoutParams middleparams = new RelativeLayout.LayoutParams( dpToPx(64), dpToPx(64));
middleparams.leftMargin=dpToPx((Screendp()/3));
middle.setLayoutParams(middleparams);
RelativeLayout.LayoutParams rightparams = new RelativeLayout.LayoutParams( dpToPx(64), dpToPx(64));
rightparams.leftMargin=dpToPx((Screendp()/3)*2);
right.setLayoutParams(rightparams);
This is working and i have tried this.

fit size of parent layout

I have a simple linear layout and want to divide the screen into two equally sized parts.
In the upper one, I want to put a SurfaceView that has exactly the same size as its parent, i.e. half of the screen. Unfortunately, it always either takes all the screen or nothing (depending on the configuration).
Why is that and how can I change it?
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="2"
android:orientation="vertical">
<LinearLayout android:id="#+id/layoutUpperDaw"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#192832">
<com.example.MySurvfaceView
android:id="#+id/id_mySurfaceView"
android:layout_width="match_parent"
android:layout_height="0pt"
android:layout_weight="1"
OR
android:layout_height="match_parent"
>
</com.example.MySurvfaceView>
</LinearLayout>
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#193222">
...
</LinearLayout>
</LinearLayout>
When you provide weight you have to set height or weight to 0dp as below.
<LinearLayout android:id="#+id/layoutUpperDaw"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#192832">
and
<com.example.MySurvfaceView
android:id="#+id/id_mySurfaceView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
>
Update: Answer above is correct about weight usage, make sure either hight or width is 0dp at all places where you used weight.
You don't really need nested LinearLayout. Following should work.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.example.MySurvfaceView
android:id="#+id/id_mySurfaceView"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
>
</com.example.MySurvfaceView>
<LinearLayout android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#193222">
</LinearLayout>
</LinearLayout>
Programmatically:
Find the parent layout.
GridLayout gridLayout =(GridLayout)findViewById(R.id.gridLayout);`
Get measured height and Width of parent.
int height = gridLayout.measuredHeight();
int width = gridLayout.measuredWidth();
3.Calculate child view height and width.For example two child each taking 50% of height in the parent but taking full width of parent:
int childHeight = height/2;
int childWidth = width;
4.Get instanceof LayoutParams depending on parent type.
GridLayout.LayoutParams params = new GridLayout.LayoutParams();
5. Set height and width on layout params.
params.width = childWidth;
params.height = childHeight;
6.Create child view and set Layout params.
ImageView imageview = new ImageView();
imageview.setLayoutParams(params);
7.Add child View to parent.
gridLayout.addView(ImageView);

set remaining height to view at runtime

I am writing an application where need to assign rest of screen space to view.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/txtView_1"
android:layout_width="match_parent"
android:layout_height="100dp" />
<TextView
android:id="#+id/txtView_2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Test Text" />
</LinearLayout>
and to set runtime I am using following:
private void process() {
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int txtView1Height = txtView_1.getHeight();
LayoutParams layoutParams = (LayoutParams) txtView_2.getLayoutParams();
layoutParams = new LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
(metrics.heightPixels - txtView1Height));
txtView_2.setLayoutParams(layoutParams);
}
But here it's taking not exact same remaining height..since textview sting not placing in center(this is how I simply check)...it might be mistaken to set height in pixel.
Any suggestion here?
You can use weight xml parameter
<TextView
android:id="#+id/txtView_2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1.0"
android:gravity="center"
android:text="Test Text" />
or in your case simple set height to match_parent
android:layout_height=match_parent
To check even more simpler set gravity to bottom. If you still want to do this programmatically dont use DisplayMetrics to get height (Action Bar and Software Buttons are also a part of display) use your root LinearLayout height. Also check if txtView1Height is not 0 (maybe view was not drawed at the moment of calculation)

LinearLayout height not getting set programmatically

In my app, I've a layout like:
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:id="#+id/belowAcionBar"
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="horizontal">
</LinearLayout>
</FrameLayout>
I need to set the height of LinearLayout belowAcionBar dynamically. This view needs to be shown just below ActionBar.
To set the height I'm using below code:
View panelView = findViewById(R.id.belowAcionBar); // This gives object of LinearLayout
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) panelView.getLayoutParams();
params.height = 48; // In dp
panelView.setLayoutParams(params);
Issue 1:
Since belowAcionBar is a LinearLayout, first I tried of using LayoutParams as LinearLayout.LayoutParams, rather than FrameLayout.LayoutParams.
But it thre a runtime error Can't cast FrameLayout.LayoutParams to LinearLayout.LayoutParams.
Why it is getting panelView.getLayoutParams() as FrameLayout?
Issue 2:
Even after using code above, my view belowAcionBar is appearing to be much less than 48dp. Seems like it is being partially hidden behind ActionBar.
Issue 3:
If I change the layout to:
<FrameLayout
android:id="#+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout android:orientation="vertical"
android:id="#+id/belowAcionBar"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="#color/purple_dark" >
</LinearLayout>
</LinearLayout>
</FrameLayout>
And change the java code to:
View panelView = findViewById(R.id.belowAcionBar);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) panelView.getLayoutParams();
params.height = 48; // In dp
panelView.setLayoutParams(params);
Then my code works perfectly, but adds extra Layout. Why it is working now?
Thanks in advance.

layout_height should be a function of layout_width

Assuming portrait mode, I have an ImageView who's image will be of variable size (yet always square). I would like the ImageView's width to always be equal to the layout's width (fill_parent) and as you can see the scaleType is "centerCrop" which will scale.
The problem is that if I set the *layout_height* also to "fill_parent" then, being that centerCrop retains the original aspect ratio, the height takes precedence and the image is cropped on the left and right. (this of course assumes a screen that is taller than it is wide). However, if I set the layout_height to "wrap_content", then the height is no longer scaled and I end up with a cropped rectangle. It does this because it respects the original height of the image.
Is there a layout_height setting that will give precedence to a layout_width of "fill_parent"?
<ImageView
android:id="#+id/iv_image"
android:layout_width="fill_parent"
android:layout_height="?"
android:layout_below="#id/header"
android:layout_centerHorizontal="true"
android:contentDescription="#string/cd_image"
android:padding="0dp"
android:scaleType="centerCrop"
android:src="#drawable/blank_album" />
Removing the android:layout_height attribute causes a crash:
java.lang.RuntimeException: Binary XML file line #16: You must supply a layout_height attribute.
Setting android:layout_height="0dp" crushes the image vertically.
Answer: Using a combination of responses from other users, I was able to find a simple solution that works well for me.
First, the image view has this configuration (note the fitStart):
<ImageView
android:id="#+id/iv_album"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_below="#id/header"
android:layout_gravity="top"
android:background="#FF00FF00"
android:contentDescription="#string/app_name"
android:padding="0dp"
android:scaleType="fitStart"
android:src="#drawable/blank_album" />
Then programmatically, a small modification to the height of the image to match the width (within Activity.onResume())
ImageView iv = (ImageView)findViewById(R.id.iv_album);
boolean bPost = iv.post(
new Runnable()
{
public void run()
{
ImageView iv = (ImageView)findViewById(R.id.iv_album);
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)iv.getLayoutParams();
params.width = ASong.this.findViewById(R.id.song_view_layout_top).getWidth();
params.height = params.width;
iv.setLayoutParams(params);
}
});
if (bPost == false)
{
throw new RuntimeException("runnable not posted");
}
I had to deal with this issue yesterday. This is the XML that solved my problem:
<ImageView
android:id="#+id/character"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_alignParentBottom="true"
android:background="#android:color/transparent"
android:scaleType="fitCenter"
android:src="#drawable/ma_un1_001" />
see thread here: Center drawable and scale height
To cut a long story short:
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="fitCenter"
Alternatively, you can do it programmatically:
Surround the ImageView with a LinearLayout
<LinearLayout
android:id="#+id/container"
android:layout_below="#id/header"
android:layout_centerHorizontal="true"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:id="#+id/iv_image"
android:layout_width="fill_parent"
android:layout_height="?"
android:contentDescription="#string/cd_image"
android:padding="0dp"
android:scaleType="centerCrop"
android:src="#drawable/blank_album" />
</LinearLayout>
Then, in your onCreate(), insert
findViewById(R.id.container).post(
new Runnable() {
public void run() {
LinearLayout container = (LinearLayout)findViewById(R.id.container);
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams)container.getLayoutParams();
params.height = params.width;
container.setLayoutParams(params);
}}
);
The code must be into post() because the main process can't directly modify the layout structure.

Categories

Resources