17

I'm using recycler view with GirdLayout Manager for creating bus layout. My problem is with spacing, I'm populating data according to row column.

This is how I'm getting layout:

enter image description here

This is how I want my layout to be:

enter image description here

I want the item at row 3 and column 2 beside sleeper seat at row 2 column 0 like shown in the picture above. How can I remove that space, item should accommodate according to its upper item.

customGridAdapter = new CustomGridViewAdapter(getActivity(), busSeatModel, false, fareCategory, BusSeatLayout.this);
                       RtlGridLayoutManager gridLayoutManager = new RtlGridLayoutManager(getActivity(), busSeatModel.getMaxLowerColumn());
                       seatLayout.setLayoutManager(gridLayoutManager);
                       seatLayout.setAdapter(customGridAdapter);

This is my customGridAdapter onBindViewHolder:

public class CustomGridViewAdapter extends RecyclerView.Adapter<CustomGridViewAdapter.MyViewHolder> {

    Context context;
    BusSeatModel busSeatModel;
    HashMap<Integer, HashMap<Integer, BusSeatItemModel>> data = new HashMap<>();
    LayoutInflater inflater;
    boolean upper;
    HashMap<Integer, BusSeatItemModel> seatLowerModels;
    BusSeatItemModel lowerModel;
    int maxColumn = 0;
    int maxRow = 0;
    BusSeatLayout busSeatLayout;
    int fare;

    public CustomGridViewAdapter(Context context, BusSeatModel busSeatModel, boolean upper, int fare, BusSeatLayout busSeatLayout) {
        this.context = context;
        this.busSeatModel = busSeatModel;
        inflater = LayoutInflater.from(context);
        this.fare = fare;
        this.busSeatLayout = busSeatLayout;
        this.upper = upper;
        if (upper) {
            data = busSeatModel.getBusSeatUpperModels();
            maxColumn = busSeatModel.getMaxUpperColumn();
            maxRow = busSeatModel.getMaxUpperRow();
        } else {
            data = busSeatModel.getBusSeatLowerModels();
            maxColumn = busSeatModel.getMaxLowerColumn();
            maxRow = busSeatModel.getMaxLowerRow();
        }
    }


    @Override
    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        View view = inflater.inflate(R.layout.seatrow_grid, parent, false);

        MyViewHolder myViewHolder = new MyViewHolder(view);

        return myViewHolder;
    }

    @Override
    public void onBindViewHolder(MyViewHolder holder, int position) {
        try {

            int row = GetRow(position);
            int column = GetCol(position);

            Log.d(" Row Column  ", "" + row + "  " + column);

            seatLowerModels = new HashMap<>();

            if (data.containsKey(row)) {
                seatLowerModels = data.get(row);
                if (seatLowerModels.containsKey(column)) {
                    lowerModel = seatLowerModels.get(column);
                    Log.v(" same fare ", " model fare " + lowerModel.getBaseFare() + " category selected " + fare);
                    if (fare == -1) {
                        Log.v("  fare  is all ", "++++    ");

                        holder.imageItem.setImageResource(lowerModel.getDrawableName(false));

                    } else {
                        Log.v("  fare  is not all ", "");
                        if (lowerModel.getBaseFare() == fare) {
                            Log.v("  fare  is same ", "");
                            holder.imageItem.setImageResource(lowerModel.getDrawableName(false));
                        } else {
                            Log.v("  fare  is diff ", "");
                            holder.imageItem.setImageResource(lowerModel.getDrawableName(true));
                        }
                    }
                    holder.imageItem.setVisibility(View.VISIBLE);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private int GetCol(int pos) {
        int col = pos % (maxColumn);
        return col;
    }

    private int GetRow(int pos) {
        int row = pos / (maxColumn);
        return row;
    }

    @Override
    public int getItemCount() {
        return maxColumn * maxRow;
    }


    public class MyViewHolder extends RecyclerView.ViewHolder {

        ImageView imageItem;


        public MyViewHolder(View itemView) {
            super(itemView);


            imageItem = (ImageView) itemView.findViewById(R.id.item_image);}
    }
}

This is the recyclerview:

<RelativeLayout
            android:id="@+id/rlRecycler"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="#ffffff"
            android:gravity="center">

            <android.support.v7.widget.RecyclerView
                android:id="@+id/rvFareCategory"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerHorizontal="true"
                android:background="#ffffff"
                android:paddingBottom="6dip"
                android:paddingTop="8dip"></android.support.v7.widget.RecyclerView>
        </RelativeLayout>

And, seat layout XML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content">

<ImageView
    android:id="@+id/item_image"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@null"
    android:padding="4dp"
    android:visibility="invisible"></ImageView>

</RelativeLayout>
j.developer
  • 474
  • 2
  • 5
  • 15
Rohit Raich
  • 492
  • 4
  • 15
  • Post your *xml layout* code. – Jay Rathod Sep 12 '16 at 12:03
  • @jayroider I've updated xml code – Rohit Raich Sep 12 '16 at 12:09
  • Are these rows added dynamically or using this *layout* itself ? – Jay Rathod Sep 12 '16 at 12:45
  • these rows are added dynamically depending on the data. I've passed seatlayout.xml to adapter – Rohit Raich Sep 12 '16 at 12:47
  • Could you show me the full code for both *Activity* and *Adapter* ? – Jay Rathod Sep 12 '16 at 12:49
  • @jaydroider I've updated it please check. – Rohit Raich Sep 14 '16 at 11:01
  • 1
    A GridLayoutManager can't help you with that layout. What you're looking for is a StaggeredGridLayoutManager which could be easily adapted to replicate the layout(I've made a small example here https://gist.github.com/luksprog/230c97dfb00d71141e2f3b5b26699e00), another alternative would be a LinearLayoutManager with different row types(where a row will consist of a big seat + space + 4 small seats). – user Sep 15 '16 at 08:43
  • @Luksprog your code Working perfectly,Post your code as answer https://gist.github.com/luksprog/230c97dfb00d71141e2f3b5b26699e00 – appukrb Jun 15 '17 at 09:38

2 Answers2

0

The problem, of course, arises from the fact that your elements don't have the same height. You need to assign different row spans to the elements. I would suggest assigning the taller elements (the ones on the left) a row span of 2 and 1 for the smaller ones.

I think you could do it with a trick like setting your grid layout manager to have a horizontal orientation and use GridLayoutManager.setSpanSizeLookup(..) to control the span (since yours is horizontal now, the span would act on rows). This would require you to probably rework the logic of getting your elements from the backing array. The alternative would be I am afraid (as far as I know) to implement your own custom layout manager.

N.T.
  • 2,601
  • 1
  • 14
  • 20
  • sorry but i'm completely new with GridLayout Manager, how can i Set span size of depending on the row – Rohit Raich Sep 12 '16 at 13:19
  • Let's say position 0 needs to span 2 rows and the rest just one: layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { @Override public int getSpanSize(int position) { if (position == 0) return 2; return 1; } }); – N.T. Sep 12 '16 at 14:37
  • please check I've changed images for better understanding what i want to achieve – Rohit Raich Sep 14 '16 at 10:33
  • Looking over this again, I stumbled across `StaggeredGridLayoutManager`. This should work, given you can control the size of your images. – N.T. Sep 14 '16 at 12:25
  • i tried StaggeredGridLayout but the layout becomes so messy because there's no empty space was left, so column 1 will not be visible – Rohit Raich Sep 14 '16 at 12:29
  • You can always play with padding and margins for the views, but worst things come, what prevents you from adding invisible views for the space (or use `Space`)? – N.T. Sep 14 '16 at 12:36
  • row 3 is starting after row 2 bt i want to omit row 3,0 position as there's no item associated with it – Rohit Raich Sep 14 '16 at 12:46
0

I suggest implementing your recycler view item layout as a TableLayout or a GridLayout, they provide more flexibility in defining row/column spans.

Some useful links:

http://android-pro.blogspot.com.eg/2010/02/table-layout.html https://developer.android.com/guide/topics/ui/layout/grid.html

Mina Wissa
  • 10,923
  • 13
  • 90
  • 158
  • using TableLayout or GridLayout how can i remove that spacing,I tried using Table and GridLayout bt row 3 was starting after row 2 only, i want to somewhat overlap row 3 on row 2 as shown in image. – Rohit Raich Sep 19 '16 at 09:48
  • I'm not sure but maybe you can try to set the items' layout_gravity to top – Mina Wissa Sep 19 '16 at 10:00
  • i tried, the layout look same as it, the pic i've shared has gravity top only – Rohit Raich Sep 19 '16 at 10:43