To achieve this behaviour to align all items to the bottom of RecyclerView you need to set the flag setStackFromEnd(true)
When stack from bottom is set to true, the list fills its content
starting from the bottom of the view
but this flag is not supported by the GridLayout throwing an exception like:
GridLayoutManager does not support stack from end. Consider using
reverse layout
but even using setReverseLayout(true) in GridLayoutManager it renders the items from bottom to top and from left to right which is not the result you want even reversing the data of your list.
Possible Solutions:
Use GridLayoutManager and add top padding only to the first columns to fill the remaining top area or even use dummy empty columns.
Use a LinearLayout with setStackFromEnd(true) which works as expected where each item is rendered from bottom to top of RecyclerView, and each item row (Item View) holding eg: 4 views (the number of columns) with equal width. Of course in that way each Item model in the list must hold 4 data one for each column.
If you choose the second option you can prepare your columns data for each row like the below code snippet:
List<ItemModel> data = new ArrayList<>();
int listCnt = 14;
for(int i=0; i<listCnt; i++){
if(i%4 == 0) {
String dataCol1 = i < listCnt ? String.valueOf(i) : "";
String dataCol2 = (i + 1) < listCnt ? String.valueOf(i + 1) : "";
String dataCol3 = (i + 2) < listCnt ? String.valueOf(i + 2) : "";
String dataCol4 = (i + 3) < listCnt ? String.valueOf(i + 3) : "";
data.add(new ItemModel(dataCol1, dataCol2, dataCol3, dataCol4));
}
}
//set LinearLayoutManager
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, RecyclerView.VERTICAL, false);
linearLayoutManager.setStackFromEnd(true);
recyclerView.setLayoutManager(linearLayoutManager);
//set adapter
RecyclerViewAdapter adapter = new RecyclerViewAdapter(data);
recyclerView.setAdapter(adapter);
where ItemModel holds the data for each row like:
public class ItemModel {
public String dataCol1="", dataCol2="", dataCol3="", dataCol4="";
public ItemModel(String dataCol1, String dataCol2, String dataCol3, String dataCol4) {
this.dataCol1 = dataCol1;
this.dataCol2 = dataCol2;
this.dataCol3 = dataCol3;
this.dataCol4 = dataCol4;
}
}
And of course in your adapter you have to set the columns Visibility to View.INVISIBLE for those who don't have any data and View.VISIBLE for those who have.
Example of adapter can be like below:
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
private List<ItemModel> mData;
public RecyclerViewAdapter(List<ItemModel> data) {
this.mData = data;
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list_row, parent, false);
return new ItemViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
ItemModel itemModel = mData.get(position);
if(holder instanceof ItemViewHolder) {
((ItemViewHolder) holder).bind(itemModel);
}
}
@Override
public int getItemCount() {
return mData.size();
}
public class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView itemTextView1, itemTextView2, itemTextView3, itemTextView4;
public ItemViewHolder(View itemView) {
super(itemView);
itemTextView1 = itemView.findViewById(R.id.itemTextView1);
itemTextView2 = itemView.findViewById(R.id.itemTextView2);
itemTextView3 = itemView.findViewById(R.id.itemTextView3);
itemTextView4 = itemView.findViewById(R.id.itemTextView4);
itemTextView1.setOnClickListener(this);
itemTextView2.setOnClickListener(this);
itemTextView3.setOnClickListener(this);
itemTextView4.setOnClickListener(this);
}
public void bind(ItemModel itemModel){
itemTextView1.setText(itemModel.dataCol1);
itemTextView2.setText(itemModel.dataCol2);
itemTextView3.setText(itemModel.dataCol3);
itemTextView4.setText(itemModel.dataCol4);
itemTextView1.setVisibility(TextUtils.isEmpty(itemModel.dataCol1) ? View.INVISIBLE : View.VISIBLE);
itemTextView2.setVisibility(TextUtils.isEmpty(itemModel.dataCol2) ? View.INVISIBLE : View.VISIBLE);
itemTextView3.setVisibility(TextUtils.isEmpty(itemModel.dataCol3) ? View.INVISIBLE : View.VISIBLE);
itemTextView4.setVisibility(TextUtils.isEmpty(itemModel.dataCol4) ? View.INVISIBLE : View.VISIBLE);
}
@Override
public void onClick(View v) {
int cId = v.getId();
if(cId == itemTextView1.getId()){
//get col1 data
String dataCol1 = mData.get(getAdapterPosition()).dataCol1;
}
else if(cId == itemTextView2.getId()){
//get col2 data
String dataCol2 = mData.get(getAdapterPosition()).dataCol2;
}
else if(cId == itemTextView3.getId()){
//get col3 data
String dataCol3 = mData.get(getAdapterPosition()).dataCol3;
}
else if(cId == itemTextView4.getId()){
//get col4 data
String dataCol4 = mData.get(getAdapterPosition()).dataCol4;
}
}
}
}
where the list item R.layout.item_list_row which holds the 4 column views can be like below:
<?xml version="1.0" encoding="utf-8"?>
<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="50dp"
android:orientation="horizontal">
<TextView
android:id="@+id/itemTextView1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:gravity="center"
android:layout_weight="1"
android:background="@android:color/holo_blue_light"
android:textColor="@android:color/black"
tools:text="1"/>
<TextView
android:id="@+id/itemTextView2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:gravity="center"
android:layout_weight="1"
android:background="@android:color/holo_blue_light"
android:textColor="@android:color/black"
tools:text="2"/>
<TextView
android:id="@+id/itemTextView3"
android:layout_width="0dp"
android:layout_height="match_parent"
android:gravity="center"
android:layout_weight="1"
android:background="@android:color/holo_blue_light"
android:textColor="@android:color/black"
tools:text="3"/>
<TextView
android:id="@+id/itemTextView4"
android:layout_width="0dp"
android:layout_height="match_parent"
android:gravity="center"
android:layout_weight="1"
android:background="@android:color/holo_blue_light"
android:textColor="@android:color/black"
tools:text="4"/>
</LinearLayout>
And of course if you have a different span count number you can make different ViewHolder types in the RecyclerView Adapter.
Results for option 2 with RecyclerView height to be match_parent, 300dp and wrap_content respectively will be like below. RecyclerView has the grey background:
