GridLayout(not GridView) - Spaces between the cells - android

I am using GridLayout(support) for displaying ImageViews in my application. There are 3 columns and 5 rows. The problem is that the cells in the GridLayout automatically get some space between them. I am not setting any padding or margin for the cells. Please refer to the image below. All cells are added dynamically and here is how I add these cells.
Getting Screen Width and Height:
Point size = new Point();
getWindowManager().getDefaultDisplay().getSize(size);
screenWidth = size.x;
screenHeight = size.y;
rowHeight = (int) (screenHeight * 0.2);
Adding View to GridLayout:
GridLayout.LayoutParams params = new GridLayout.LayoutParams(
getSpec(rowColumn[0]), getSpec(rowColumn[1]));
params.height = rowHeight;
if (rowColumn[1].equalsIgnoreCase("col_full")) {
params.width = (int) (screenWidth);
} else if (rowColumn[1].equalsIgnoreCase("col_two_part")) {
params.width = (int) (screenWidth * 0.6);
} else {
params.width = (int) (screenWidth * 0.3);
}
ImageButton image = (ImageButton) imageHashMap
.get(reOrderedButtonsListCopy.get(i));
image.setLayoutParams(params);
gridLayout.addView(image, params);
XML Layout:
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.xx.xxx"
android:id="#+id/scrollView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<android.support.v7.widget.GridLayout
xmlns:app="http://schemas.android.com/apk/res/com.xx.xxx"
android:id="#+id/gridlayout_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="2dp"
app:columnCount="3"
app:rowCount="5" >
</android.support.v7.widget.GridLayout>
</LinearLayout>
</ScrollView>
Current result:
The red lines show the spaces in between the cells. Also, there is some space on the left side of GridLayout. I have only given 2dp as layout_margin. Any reasons why this padding occurs?
[EDIT]
Making the following changes removed the spacings.
gridLayout = (GridLayout) findViewById(R.id.gridlayout_main);
gridLayout.setUseDefaultMargins(false);
gridLayout.setAlignmentMode(GridLayout.ALIGN_BOUNDS);
gridLayout.setRowOrderPreserved(false);
Refer to the image below.

Found the solution.
Making the following changes removed the spacings.
gridLayout = (GridLayout) findViewById(R.id.gridlayout_main);
gridLayout.setUseDefaultMargins(false);
gridLayout.setAlignmentMode(GridLayout.ALIGN_BOUNDS);
gridLayout.setRowOrderPreserved(false);
Refer to the image below.

The only solution that worked for me was to add extra columns in the GridLayout like android:columnCount="7" and then the column that needs more width set to 3 or more. The more space you want to give to that column. It then automatically reserves more space for those columns. The whole GridLayout works as a stretching thing. The columnWeight says how much a column can stretch.

Related

Programmatically setting height of LinearLayout inside ScrollView not working

I have a ScrollView whose unique child is a LinearLayout:
<ScrollView
android:id="#+id/d_scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<LinearLayout
android:id="#+id/d_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/transparency"
android:orientation="vertical"/>
</ScrollView>
I later dynamically add children to the LinearLayout by using a LayoutInflator (let's say 5 children in this example), and they all have a weight of 1 (so equal heights). I want to only have 4.5 children visible at a time. To do this, I have used a post method to do change the layout_height property of the LinearLayout once the height of the ScrollView is known:
if (n > visibleItems) { // here n = 5 and visibleItems = 4.5
dScroll.setFillViewport(false);
dScroll.post(() -> {
int height = dScroll.getHeight();
ViewGroup.LayoutParams lp = dLayout.getLayoutParams();
lp.height = (int) Math.round(n * height / visibleItems);
dLayout.setLayoutParams(lp);
});
}
However, when I do this, the LinearLayout and its children behave as if their height was set to wrap_content (which is not the case). When using the Layout Inspector in Android Studio, I find that the layout_height of the LinearLayout is set to 1071 (the correct computed value), but the getHeight() method returns 578.
I have tried several combinations of requestLayout(), invalidate() and forceLayout() but it didn't change anything.
Keeping the fillViewport property of the ScrollView to true makes the LinearLayout take the height of the ScrollView, so in this case 964px instead of the 1071 that I want.
Edit: the problem really comes from LinearLayout. If I add a RelativeLayout between the ScrollView and LinearLayout like so:
<ScrollView
android:id="#+id/d_scroll"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<RelativeLayout
android:id="#+id/d_rel"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/d_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/transparency"
android:orientation="vertical"/>
</RelativeLayout>
</ScrollView>
and apply the new height to the RelativeLayout instead:
if (n > visibleItems) { // here n = 5 and visibleItems = 4.5
dScroll.setFillViewport(false);
dScroll.post(() -> {
int height = dScroll.getHeight();
ViewGroup.LayoutParams lp = dRel.getLayoutParams();
lp.height = (int) Math.round(n * height / visibleItems);
dRel.setLayoutParams(lp);
});
}
then the RelativeLayout takes the correct height (1071px), but the LinearLayout within it (that is in match_parent height) is still only 578px high.

Filling the whole screen with Gridview items

I have a GridView (with 2 columns and 2 rows) and want to stretch the rows to fill the whole screen. It should look the same on all devices.
That means I don't want some empty space under the last row. So I searched a little bit and found a solution to set the minimum height of the GridView dynamically with following code:
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
int width = metrics.widthPixels;
int height = metrics.heightPixels;
In addition I added these lines of code in my Adapter:
gridView = inflater.inflate(R.layout.act_main_menu_sub, null);
gridView.setMinimumHeight(ActMainMenu.height/2);
But now it looks like this:
The View is scrollable now and the items have the same size. But it doesn't fit on the screen.
Here is the code of my layout including the GridView:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/layout_main_menu"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#b2b2b2"
android:orientation="vertical">
<!-- android:layout_height="wrap_content" -->
<android.support.v7.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:fitsSystemWindows="true"
android:minHeight="?attr/actionBarSize"
android:padding="2dp"
app:titleMarginStart="20dp"
app:titleTextAppearance="#style/MyMaterialTheme.Base.TitleTextStyle"
app:titleTextColor="#color/textColorPrimary">
<TextView
android:id="#+id/toolbar_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="MASTERFITNESS TRAINERSCHULUNG"
android:textColor="#android:color/white"
android:textStyle="bold|italic"/>
</android.support.v7.widget.Toolbar>
<!--android:columnWidth="160dp"-->
<GridView
android:id="#+id/grid_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_margin="10dp"
android:gravity="center"
android:horizontalSpacing="20dp"
android:numColumns="2"
android:stretchMode="columnWidth"
android:verticalSpacing="20dp"></GridView>
</LinearLayout>
What is the problem here?
The problem with your 2nd screen shots in the height calculation. metrics.heightPixels gives you the full height of the screen, including the toolbar and any margins you have. These should 1st be subtracted out, then divide the screen in half.
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);
// your layout has 10dp margin (top & bottom) + 20 dp between grid items, 10+10+20=40
int marginSizeDp = 40;
float scale = metrics.density;
int marginSizePx = Math.round (marginSizeDp * scale);
int appBarHeight = getAppBarHeight();
int height = metrics.heightPixels;
int minHt = Math.round((height - marginSizePx - appBarHeight)/2);
gridView.setMinimumHeight(minHt);
Get the toolbar height thanks to AZ13 at https://stackoverflow.com/a/7167086/7292819
// returns height of app bar in pixels
private int getAppBarHeight() {
final TypedArray styledAttributes = getTheme().obtainStyledAttributes(
new int[] { android.R.attr.actionBarSize });
int appBarHeight = (int) styledAttributes.getDimension(0, 0);
styledAttributes.recycle();
return appBarHeight;
}
Truthfully, if this layout is static (there's only 4 items, no scrolling, little or no changing of the content of each item), I probably wouldn't bother with a GridView & adapter. A RelativeLayout or GridLayout might be better.

Android XML - ImageView scrolling

A sprite on my android game is set to fall by 5 pixels every 100 milliseconds, this works fine the only problem is that the ImageView itself is only 53dp high, if I make it any bigger the image inside scales with it. Since the ImageView is only 53dp high the image disappears after 1100 milliseconds as it scrolls outside the boundaries of the imageview.
I need the layout height of the ImageView to fill_parent but I need the image to stay the same size instead of scaling with it, here's my current code:
<ImageView
android:id="#+id/blueman"
android:layout_width="0dip"
android:layout_height="53dp"
android:paddingRight="300dp"
android:layout_weight="0.03"
android:src="#drawable/fall" />
Thanks in advance :)
since you didn't give the full code of the layout, I'll make some assumptions...
you're talking about setting your sprite's height to the screen's height without scaling?
There should be a difference between your screen size (that is the root layout item) and the sprites in it. I guess you declared your layout as...:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
style="?gameBackground"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="#+id/btTap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="14dp"
android:layout_marginTop="350dp"
android:background="#drawable/tap"
android:visibility="visible" />
<Button
android:id="#+id/btCellR1C1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginLeft="490dp"
android:layout_marginTop="155dp"
android:background="#drawable/cell_red" />
The only thing I had to cope with, was the scaling of my sprites depending on the device's resolution with such a method:
public static void scaleView(View view, int top, int left, int width,
int height) {
top = Math.round(top * scaleY);
left = Math.round(left * scaleX);
width = Math.round(width * scaleX);
height = Math.round(height * scaleY);
LayoutParams params = new LayoutParams(LayoutParams.WRAP_CONTENT,
LayoutParams.WRAP_CONTENT);
params.height = height;
params.width = width;
params.topMargin = top;
params.leftMargin = left;
view.setLayoutParams(params);
view.setSoundEffectsEnabled(false);
}
Please give us more details to help you
Best regards
Serge

xml get width and set to android:height

<LinearLayout
android:layout_width="match_parent"
android:layout_height=" "
android:orientation="vertical" >
Here's the thing, lets say i have this LinearLayout that has a width of match_parent, so the width of the LinearLayout depends on the width of the device. What i dont know is how could i set the android:layout_height=" " value to correspond on the value of the android:layout_width="match_parent" so i could have a Square LinearLayout i know i can do this using LayoutParams but is there a way to do it on xml? Thank you guys..
First get screen width
Display mDisplay = activity.getWindowManager().getDefaultDisplay();
int width = mDisplay.getWidth();
int height = mDisplay.getHeight();
Set Size to Layout
LinearLayout layout = (LinearLayout)findViewById(R.id.LayoutID);
// Gets the layout params that will allow you to resize the layout
LayoutParams params = layout.getLayoutParams();
// Changes the height and width to the specified *pixels*
params.height = width;
params.width = width;
layout.setLayoutParams(params);
In XML:
<LinearLayout
android:layout_width="0dp"
android:layout_height="0dp"
android:id="#+id/LayoutID"
android:orientation="vertical" >

android - how does LayoutParams work?

I am a bit confused about this. I have an app where user draws rectangular text objects. I added some textviews in a relative layout in my xml (lets say that I have a maximum of 3 text objects). The objects can be moved and resized. I added this code for each textView
TextView tv=(TextView) findViewById(R.id.text1);
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(LayoutParams.FILL_PARENT,LayoutParams.FILL_PARENT);
System.out.println(texts.get(i).Sx+ " , "+texts.get(i).Sy+ " , "+ texts.get(i).Lx+ " , "+texts.get(i).Ly);
if(texts.get(i).Sx<=texts.get(i).Lx){
if(texts.get(i).Sy<=texts.get(i).Ly){
lp.setMargins((int)texts.get(i).Sx, (int)texts.get(i).Sy, (int)texts.get(i).Lx, (int)texts.get(i).Ly);
} else{
lp.setMargins((int)texts.get(i).Sx, (int)texts.get(i).Ly, (int)texts.get(i).Lx, (int)texts.get(i).Sy);
}
} else{
if(texts.get(i).Sy<=texts.get(i).Ly){
lp.setMargins((int)texts.get(i).Lx, (int)texts.get(i).Sy, (int)texts.get(i).Sx, (int)texts.get(i).Ly);
} else{
lp.setMargins((int)texts.get(i).Lx, (int)texts.get(i).Ly, (int)texts.get(i).Sx, (int)texts.get(i).Sy);
}
}
tv.setLayoutParams(lp);
tv.setWidth((int)(texts.get(i).width));
tv.setHeight((int)(texts.get(i).height));
tv.setTextSize(texts.get(i).textSize);
tv.setText(text.text);
tv.setTextColor(Color.WHITE);
tv.requestLayout();
Sx, Sy are the starting coos of the object in pixels and Lx, Ly the ending coos.
in the xml I added this:
<RelativeLayout
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:id="#+id/texts" >
<TextView
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:id="#+id/text1" />
<TextView
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:id="#+id/text2" />
<TextView
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:id="#+id/text3" />
</RelativeLayout>
This seems to work as for in placing the text in the right place. But the width and height of the textview does not seem to be right. Is this a problem of setting the margins in pixels? Some enlightenment would be very useful right now
LayoutParams are used to align your view dynamically. You can add rule to your params like below, above, bottom, top, align, margin and all(same like you do through xml) then finally you can set this layout params to your view. E.g :
// Set the params eg. for a button.
RelativeLayout.LayoutParams button_params = new RelativeLayout.LayoutParams(RelativeLayout
.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
button_params.addRule(RelativeLayout.LEFT_OF,
any_view.getId());
button_params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM,
RelativeLayout.TRUE);
button_params.bottomMargin = screen_height / 15;
button_params.rightMargin = 20;
button.setLayoutParams(button_params);
You first set width/height to FILL_PARENT, then you overwrite it with px ?
try something like this
View temp = this.findViewById(recent);
RelativeLayout.LayoutParams relativeParams = (LayoutParams) temp.getLayoutParams();
relativeParams.setMargins(0, 0, 0, 50); // llp.setMargins(left, top, right, bottom);
relativeParams.width = 123;
relativeParams.height = 123;
temp.setLayoutParams(relativeParams);

Categories

Resources