Android GridLayout with dynamic number of columns per row

19
April 15, 2019, at 11:30 AM

I have cards with different width and I would like to create a Grid Layout where width = match the parent (filling the screen) and fixed height. I would like to set the cards in the Grid layout so the number of columns changes accordingly to the width of the elements that can fit the row.

So the elements will be set in a horizontal row till they can fit the screen and then go to the next row, with a vertical scroll when they exceed the fixed height.

I am trying to use a Grid Layout but I don't know if it the suitable solution for this. I use native Android.

Here a picture of it should look like:

Thanks.

Answer 1

You can use FlexboxLayoutManager

Add the following dependency to your build.gradle file:

implementation 'com.google.android:flexbox:0.3.2'

SAMPLE CODE

LAYOUT.XML

<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:orientation="vertical"
    tools:context=".MainActivity">
    <android.support.v7.widget.RecyclerView
      android:id="@+id/recyclerView"
      android:layout_width="match_parent"
      android:layout_height="250dp" />

</LinearLayout>

ACTIVTY CODE

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.RecyclerView;
import com.google.android.flexbox.FlexDirection;
import com.google.android.flexbox.FlexboxLayoutManager;
import com.google.android.flexbox.JustifyContent;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {
    RecyclerView recyclerView;
    ArrayList<String> arrayList = new ArrayList<>();
    DataAdapter adapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        recyclerView = findViewById(R.id.recyclerView);
        initArray();
        FlexboxLayoutManager layoutManager = new FlexboxLayoutManager(this);
        layoutManager.setFlexDirection(FlexDirection.COLUMN);
        layoutManager.setJustifyContent(JustifyContent.FLEX_END);
        recyclerView.setLayoutManager(layoutManager);
        adapter = new DataAdapter(this, arrayList);
        recyclerView.setAdapter(adapter);
    }
    private void initArray() {
        arrayList.add("ioreeoe");
        arrayList.add("fghfgh");
        arrayList.add("ftyjyjhghgh");
        arrayList.add("jfgewrg");
        arrayList.add("rwrewr");
        arrayList.add("ghyjtyfghh");
        arrayList.add("gfhfgh");
        arrayList.add("gfhfht");
        arrayList.add("retretret");
        arrayList.add("retret");
        arrayList.add("ioreeoe");
        arrayList.add("fghfgh");
        arrayList.add("ftyjyjhghgh");
        arrayList.add("jfgewrg");
        arrayList.add("rwrewr");
        arrayList.add("ghyjtyfghh");
        arrayList.add("gfhfgh");
        arrayList.add("gfhfht");
        arrayList.add("retretret");
        arrayList.add("retret");
        arrayList.add("ioreeoe");
        arrayList.add("fghfgh");
        arrayList.add("ftyjyjhghgh");
        arrayList.add("jfgewrg");
        arrayList.add("rwrewr");
        arrayList.add("ghyjtyfghh");
        arrayList.add("gfhfgh");
        arrayList.add("gfhfht");
        arrayList.add("retretret");
        arrayList.add("retret");
    }
}

Adapter code

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.ArrayList;
/**
 * Created by nilesh on 3/4/18.
 */
public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder> {
    Context context;
    ArrayList<String> arrayList = new ArrayList<>();
    public DataAdapter(Context context, ArrayList<String> arrayList) {
        this.context = context;
        this.arrayList = arrayList;
    }
    @Override
    public DataAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(context).inflate(R.layout.custom_layout, parent, false);
        return new ViewHolder(view);
    }
    @Override
    public void onBindViewHolder(DataAdapter.ViewHolder holder, int position) {
        holder.title.setText(arrayList.get(position));
    }
    @Override
    public int getItemCount() {
        return arrayList.size();
    }
    public class ViewHolder extends RecyclerView.ViewHolder {
        TextView title;
        public ViewHolder(View itemView) {
            super(itemView);
            title = itemView.findViewById(R.id.nilu);
        }
    }
}

custom_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">
    <TextView
        android:id="@+id/nilu"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="5dp"
        android:background="@drawable/test"
        android:padding="10dp"
        android:textColor="#050505" />
</LinearLayout>

@drawable/test

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle"  >
            <corners android:radius="30dp"/>
            <solid android:color="#d10e0e"/>
            <stroke android:width="1dip" android:color="#070fe9" />
        </shape>
    </item>
</selector>

RESULT

Answer 2

You can use Staggered GridView libraries. For eg. https://github.com/etsy/AndroidStaggeredGrid Edit: add dependency in build.gradle and in your xml you can add:

 <com.etsy.android.grid.StaggeredGridView
        android:id="@+id/itemgridfragment_gridview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:column_count="2"
        android:background="@color/white"
        app:item_margin="@dimen/fragment_landingpage_8" />
</android.support.v4.widget.SwipeRefreshLayout>
READ ALSO
I keep getting the error &ldquo;the string did not match the expected pattern&rdquo; for my fetch request

I keep getting the error “the string did not match the expected pattern” for my fetch request

I keep getting the error "the string did not match the expected pattern" for my fetch requestsI've seen some people having similar problems on here and other forums but can't pinpoint the problem

21
Unable to pass parameter to inline javascript via ng-include

Unable to pass parameter to inline javascript via ng-include

I'm trying to build a AngularJS application with few dynamic html templates using ng-includeThese html's contain inline javascript with a variable

36
Add black bar to an ion-card

Add black bar to an ion-card

I have an ion-card with a header (title and subtitle) and I need to add a black bar on top of the header

54