Heterogeneous Gridlayout

Heterogeneous GridLayout

So here is the solution I promised after one year =)
It basically uses the ViewTreeObserver to get the dimensions of the parent layout and create custom views accordingly. Since this code is one year old ViewTreeObserver might not be the best way to get the dimensions dynamically.

You can find the full source code here:
https://github.com/cdoger/Android_layout

I divided the screen into 8 equal widths and 6 equal heights. Here is a snapshot of how I laid out the views:

final RelativeLayout mainLayout = (RelativeLayout) findViewById(R.id.main_layout);
ViewTreeObserver vto = mainLayout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
final int oneUnitWidth = mainLayout.getMeasuredWidth() / 8;
final int oneUnitHeight = mainLayout.getMeasuredHeight() / 6;
/**
* 1
***************************************************************/
final RelativeLayout.LayoutParams otelParams = new RelativeLayout.LayoutParams(
oneUnitWidth * 4, oneUnitHeight);
otelParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
otelParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
// otelParams.setMargins(0, 0, 2, 0);
View1.setLayoutParams(otelParams);
/***************************************************************/

/**
* 2
***************************************************************/
final RelativeLayout.LayoutParams otherParams = new RelativeLayout.LayoutParams(
oneUnitWidth * 4, oneUnitHeight);
otherParams.addRule(RelativeLayout.ALIGN_PARENT_TOP);
otherParams.addRule(RelativeLayout.RIGHT_OF, View1.getId());
otherParams.setMargins(2, 0, 0, 0);
View2.setLayoutParams(otherParams);
/***************************************************************/
//... goes on like this

Here is the final screenshot:

Sample Image

Different heights in an Android GridLayout

how to dynamically change heights of the note cards based on their text length - you can just set the layout height to wrap_content like this:

android:layout_height="wrap_content"

You can put your items in scrollView like this:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<TextView
android:layout_width="50dp"
android:layout_height="wrap_content"
android:text="short text !!!!!!!!!!!!?!@#!@%$%$#"
android:layout_marginBottom="8dp"/>

<TextView
android:layout_width="50dp"
android:layout_height="wrap_content"
android:text="Longggggggggggggggggggggggggggggggggggggggggggggggg text very long"/>
</LinearLayout>

</ScrollView>

And it will look like this:

Sample Image

The blue line represents the separation between your 2 views.

If you want to achieve this using RecyclerView check out this post, Staggered RecyclerView and Heterogeneous GridLayout

how in GridLayout (Android) to fit the last two blocks to full width?

Have a look at SpanSizeLookup.

Something like:

val layoutManager = GridLayoutManager(activity, 2)
layoutManager.spanSizeLookup = object : GridLayoutManager.SpanSizeLookup() {
override fun getSpanSize(position: Int): Int {
return when (position) {
YOUR_CONDITION -> 2
else -> 1
}
}
}
recyclerView.layoutManager = layoutManager

Replace YOUR_CONDITION with some logic fits your requirements to make a cell twice higher.

Gridlayout changes widths

After much frustration I was unable to find a solution in the XML layout. However I did find a solution that seems to be working fairly well programatically.

I added a method called at the end of my OnCreate

public void ResizeTexts(){
Display display = getWindowManager().getDefaultDisplay();
DisplayMetrics outMetrics = new DisplayMetrics ();
display.getMetrics(outMetrics);

float density = getResources().getDisplayMetrics().density;
float dpWidth = (outMetrics.widthPixels / density);

text1.getLayoutParams().width = (int)dpWidth;
text2.getLayoutParams().width = (int)dpWidth;
text3.getLayoutParams().width = (int)dpWidth;
text4.getLayoutParams().width = (int)dpWidth;
text5.getLayoutParams().width = (int)dpWidth;
text6.getLayoutParams().width = (int)dpWidth;
}

Which i adapted from this link re-setting a TextView height programmatically

then in my XML layout I set it up with:

<GridLayout
android:layout_width="match_parent"
android:layout_height="70dp">

<TextView
android:text="points"
android:layout_height="wrap_content"
android:layout_width="10dp"
android:id="@+id/text1"
android:layout_row="0"
android:layout_column="0"
android:textAlignment="textEnd"
/>

<TextView
android:text="totals"
android:layout_height="wrap_content"
android:layout_width="10dp"
android:id="@+id/text2"
android:layout_row="1"
android:layout_column="0"

android:textAlignment="textEnd"/>

<TextView
android:text="score"
android:layout_height="wrap_content"
android:id="@+id/text3"
android:layout_width="10dp"
android:layout_row="2"
android:layout_column="0"
android:textAlignment="textEnd"/>

<TextView
android:text="123.4"
android:layout_height="wrap_content"
android:id="@+id/text4"
android:layout_width="10dp"
android:layout_row="1"
android:layout_column="1"
android:textAlignment="textEnd"/>

<TextView
android:text="1.23"
android:layout_height="wrap_content"
android:id="@+id/text5"
android:layout_width="10dp"
android:layout_row="2"
android:layout_column="1"
android:textAlignment="textEnd"/>

<TextView
android:text="1234 "
android:layout_height="wrap_content"
android:id="@+id/text6"
android:layout_width="10dp"
android:layout_row="0"
android:layout_column="1"
android:textAlignment="textEnd"/>

</GridLayout>

*the layout widths in the xml layout I was using to try and 'break' it, not actually used.

Admittedly, i'm not sure if this is the 'best' way to do this. Personally I feel like the GridLayout XML should be able to do this on it's own. But, I couldn't figure it out.

Create gridlayout.

I guess that the most straightforward way is combining horizontal and vertical LinearLayouts, setting different weights to its subviews.

This code snippet could be a start point.-

<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp" >

<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@color/green"
android:layout_margin="5dp" >

</RelativeLayout>

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical" >

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_margin="5dp"
android:background="@color/orange" >
</RelativeLayout>

<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_margin="5dp"
android:background="@color/green" >
</RelativeLayout>
</LinearLayout>
</LinearLayout>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="100dp" >

<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:layout_weight="0.5"
android:background="@color/orange" >

</RelativeLayout>

<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_margin="5dp"
android:layout_weight="1"
android:background="@color/black" >

</RelativeLayout>
</LinearLayout>

Which results in a layout like this.-

Example Layout

PinterestListView looks promising as well.

GridLayout weird behaviour

Note that this 'change' does not happen when you remove the

layout_gravity="center" from the

      <TextView
android:text="2,2 longer, also"
android:gravity="center_horizontal"
android:layout_gravity="center"/>

Apparently, this layout_gravity attribute causes the misbehavior. I think , this layout_gravity attribute tries to position the textView at the center of its parent (GridLayout) and interferes with the column 3 being resized to fill horizontal.



Related Topics



Leave a reply



Submit