0

I am working on a bus booking app. I created seat booking layout using Recyclerview and GridLayoutManager. Layout created properly. I have 4 seats in 1 row and 5 seats in the last row. So I used 5 column in GridLayoutManager. And middle column will be empty for space between 2 seats for walking. Now the problem is if I clicked on the 1st seat in will select 1s seat but image change of 5th seat. And I also set seat no in textview, so sometimes it shows correct seat no., sometimes it shows blank or sometimes wrong.

This is My Layout

SeatSelection Activity

public class SeatSelection extends AppCompatActivity implements AdapterView.OnItemClickListener{

RecyclerView recyclerView;
SeatAdapter seatAdapter;
List<SeatDetails> seatDetailsList;
TextView txtSeatNo;
ImageView imageView;
TextView fare;
public Bitmap seatIcon;
public Bitmap seatSelect;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_seat_selection);

    seatIcon = BitmapFactory.decodeResource(this.getResources(), R.drawable.seat_layout_screen_nor_avl);
    seatSelect = BitmapFactory.decodeResource(this.getResources(), R.drawable.seat_layout_screen_nor_std);

    recyclerView = (RecyclerView) findViewById(R.id.recycler);
    RecyclerView.LayoutManager layoutManager = new GridLayoutManager(this, 5);
    recyclerView.setLayoutManager(layoutManager);
    seatAdapter = new SeatAdapter(this, loadBustListSeats());
    recyclerView.setAdapter(seatAdapter);
}

public class SeatDetails {
    String name;
    boolean isBlank;
    boolean isSelected;

    public SeatDetails(String name, boolean isBlank, boolean isSelected)
    {                   
        this.name = name;
        this.isBlank = isBlank;
        this.isSelected = isSelected;
    }

    public String getName() {
        return name;
    }
}

public List<SeatDetails> loadBustListSeats() {

    seatDetailsList = new ArrayList<SeatDetails>();
    int seatSerialNumber = 1;
    for (int i = 0; i <= 60; i++) {
        if (isBlankSeat(i)) {
            seatDetailsList.add(new SeatDetails("", true, false));
        } else {
            if (i == 0) {
                seatDetailsList.add(new SeatDetails("A",  true, false));
            } else if (i == 1) {
                seatDetailsList.add(new SeatDetails("B", true, false));
            } else {
                seatDetailsList.add(new SeatDetails(String.valueOf(seatSerialNumber), true, false));
                seatSerialNumber = seatSerialNumber + 1;
            }
        }
    }
    return seatDetailsList;
}


public boolean isBlankSeat(int i) {
    if ((60 - (i - 1)) < 5)
        return false;
    else
        return i % 5 == 2 ;
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {


}



public void seatSelected(int pos)
{
    charge = charge + amt;
    imageView.setImageBitmap(seatSelect);
    txtSeatNo.setText(seatDetailsList.get(pos).getName());
    fare.setText(String.valueOf(charge));
    seatDetailsList.remove(pos);
    seatDetailsList.add(pos, new SeatDetails(seatDetailsList.get(pos).getName(), true, true));
    seatAdapter.notifyDataSetChanged();
}

public void seatDeselected(int pos)
{
    charge = charge - amt;
    imageView.setImageBitmap(seatIcon);
    fare.setText(String.valueOf(charge));
    seatDetailsList.remove(pos);
    seatDetailsList.add(pos, new SeatDetails(seatDetailsList.get(pos).getName(), true, false));
    seatAdapter.notifyDataSetChanged();
}


public class SeatAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{


    class ViewHolderOriginal extends RecyclerView.ViewHolder{

        TextView textView;
        ViewHolderOriginal(View itemView) {
            super(itemView);
            imageView= (ImageView) itemView.findViewById(R.id.item_image);
            textView = (TextView) itemView.findViewById(R.id.item_text);


        }
    }

    class ViewHolderBlank extends RecyclerView.ViewHolder{
        ViewHolderBlank(View itemView) {
            super(itemView);

        }

    }


    private  Context cntx;
    public SeatAdapter(Context context, List<SeatDetails> list){
        cntx = context;
        seatDetailsList = list;
    }

    // 0= Original view 1= Blank View
    @Override
    public int getItemViewType(int position) {
        if((getItemCount()-(position-1))<5)
            return 0;
        else
            return position % 5 == 2 ? 1 : 0;
    }

    @Override
    public int getItemCount() {
        return 60;
    }

    @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater inflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        if (viewType == 1)
            return new ViewHolderBlank(inflater.inflate(R.layout.item_blank, parent, false));
        else
            return new ViewHolderOriginal(inflater.inflate(R.layout.seatrow_grid, parent, false));
    }

    @Override
    public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
        if (holder instanceof ViewHolderBlank) {

        } else if (holder instanceof ViewHolderOriginal) {
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    SeatDetails seatDetails = seatDetailsList.get(position);

                    if (seatDetails.isSelected){
                        seatDeselected(position);

                    }
                    else
                    {
                        seatSelected(position);

                    }
                }
            });

        }
    }

}
}
  • My guess is that the value of `pos` in `seatDetailsList.get(pos)` is off by one. Could you add exception stacktrace to the question? Also see: https://stackoverflow.com/questions/15462649/index-out-of-bounds-exception-java – Timir May 07 '18 at 08:46
  • Ok i changed 'for (int i = 0; i < 60; i++)' to 'for (int i = 0; i <= 60; i++)' and it solves crashing issue. But still i have problem in selecting and deselecting seats. @Timir –  May 07 '18 at 08:49
  • Please explain your function: `public boolean isBlankSeat(int i) ` It seems you're hardcoding your blank seat checking – Mạnh Quyết Nguyễn May 07 '18 at 08:53
  • Yes it is for blank seats which is 3rd seat of row. And i want that blank space it indicate walking space. @MạnhQuyếtNguyễn –  May 07 '18 at 08:55
  • How many seats you want to create? Is that value fixed? – Mạnh Quyết Nguyễn May 07 '18 at 08:58
  • Yes Total 49 first two A and B then 1 to 47. And last row have all 5 seats visible –  May 07 '18 at 08:59
  • And i dont know why if i select 1st seat then it is selecting 1st seat as i seen in debugger but it changes image of 1st seat of 2nd row. –  May 07 '18 at 09:06
  • 61 or 49? Your function are using 60 as item count, and your loop execute 61 times `for (int i = 0; i <= 60; i++)` – Mạnh Quyết Nguyễn May 07 '18 at 10:26
  • I need total 49 seats but there is also blank seats so i written 60 –  May 07 '18 at 10:34
  • Yeah loop executes 61 but if i write i < 60 then it is crashing onClick last seat because of IndexOutOfBound –  May 07 '18 at 10:36

1 Answers1

0

Your code has multiple problems should be fixed and improve

Let review this code for selecting a seat:

public void seatSelected(int pos)
{
    charge = charge + amt;
    imageView.setImageBitmap(seatSelect);
    txtSeatNo.setText(seatDetailsList.get(pos).getName());
    fare.setText(String.valueOf(charge));
    seatDetailsList.remove(pos);
    seatDetailsList.add(pos, new SeatDetails(seatDetailsList.get(pos).getName(), true, true));
    seatAdapter.notifyDataSetChanged();
}

Suppose your list are [0, 1, 2, 3, 4], and you're going to add item at pos = 3.

First you are calling: seatDetailsList.remove(pos); -> Your list becomes [0, 1, 2, 4].

Then you are calling

seatDetailsList.add(pos, new SeatDetails(seatDetailsList.get(pos).getName(), true, true));

In this method call, you're get seatDetailsList.get(pos).getName() from list, the current pos = 3 items in the list is 4 hen you end up add a seat with number 4 to the list like this:

[0, 1, 2, 4, 4] not [0, 1, 2, 3, 4] as you expected.

Then imagine you're selecting the last seat in your list. If you remove the last index (4), then the access to get seatDetailsList.get(pos) will throw exception because you're accessing the memory outside the list (ArrayOutOfBoundIndexException).

So you could fix this simply by modify the current state of the seat, instead of remove and re-add them.

Try this:

public void seatSelected(int pos)
{
    charge = charge + amt;
    imageView.setImageBitmap(seatSelect);
    txtSeatNo.setText(seatDetailsList.get(pos).getName());
    fare.setText(String.valueOf(charge));
    //seatDetailsList.remove(pos);
    //seatDetailsList.add(pos, new SeatDetails(seatDetailsList.get(pos).getName(), true, true));
    seatDetailList.get(pos).setIsSelected(true);

    seatAdapter.notifyDataSetChanged();
}

Try doing the same thing with the seatDeselected function, and change the loop to for (int i = 0; i < 60; i++)

Edit

class ViewHolderOriginal extends RecyclerView.ViewHolder{

    TextView textView;
    ImageView imageView; // Add this as internal property

    ViewHolderOriginal(View itemView) {
        super(itemView);
        imageView= (ImageView) itemView.findViewById(R.id.item_image);
        textView = (TextView) itemView.findViewById(R.id.item_text);


    }
}

And in your listener:

   holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SeatDetails seatDetails = seatDetailsList.get(position);

                if (seatDetails.isSelected){
                    seatDeselected(position);
                    holder.getImageView().setImageBitmap(seatSelect); // Modify state

                }
                else
                {
                    seatSelected(position);
                    holder.getImageView().setImageBitmap(seatSelect); // Modify state
                }
            }
        });
Mạnh Quyết Nguyễn
  • 17,677
  • 1
  • 23
  • 51
  • Yes now now bug ratio goes down and looks perfect when selecting and deselecting as i m showing seat no. in textview. But it is not changing icon of selected seat. –  May 07 '18 at 11:15
  • You should update your viewHolder after select/deselect seat – Mạnh Quyết Nguyễn May 07 '18 at 11:30
  • Check my image in question. If i select on any seat, it will change icon of same seat every time as shown in image. –  May 07 '18 at 11:32