0

I am trying to make an Attendance App for my College. I am using CardView Inside a Recycler View. Inside my Card View is a checkBox to mark the attendance of the particular student. The problem is that if i mark say, Student 1,2 and 3. some random cards on position 10,11,12 or anything else(random) gets marked on it's own. i know it is because of the recycler view recycling the position of those cards but since i am new to development i unfortunately do not know how implement the Check Box to give me the details of the Card checked so that i can use it. I have been through a couple of guides but haven't been able to understand. I am attaching my Adapter Class and takeAttendance Activity below. i haven't implemented anything related to the check box yet and need guidance for the same.

RECYCLER VIEW ADAPTER CLASS

package com.pkg.attendanceapp;

import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;

import com.google.android.material.checkbox.MaterialCheckBox;
import com.google.android.material.textview.MaterialTextView;

import java.util.ArrayList;

public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.StudentListViewHolder> {
    private ArrayList<StudentList> studentList;
    private ArrayList<String> presentStudents;
    private ArrayList<StudentList> absentStudents;

    public static class StudentListViewHolder extends RecyclerView.ViewHolder {

        private MaterialTextView studentName;
        private MaterialTextView studentRoll;
        private MaterialTextView attendanceTextview;
        private MaterialCheckBox checkBox;


        public StudentListViewHolder(@NonNull final View itemView) {
            super(itemView);

            studentName = itemView.findViewById(R.id.stdName);
            studentRoll = itemView.findViewById(R.id.stdRoll);
            checkBox = itemView.findViewById(R.id.checkBox);
            attendanceTextview = itemView.findViewById(R.id.studentAttendance);

        }
    }

    public RecyclerViewAdapter(ArrayList<StudentList> mStudentList){

        studentList = mStudentList;
        absentStudents = mStudentList;
    }

    @Override
    public StudentListViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        return new StudentListViewHolder(LayoutInflater.from(parent.getContext())
                .inflate(R.layout.card_view, parent, false));

    }
    @Override
    public void onBindViewHolder(@NonNull final StudentListViewHolder holder, int position) {
        StudentList currentStudent = studentList.get(position);

        holder.studentName.setText(currentStudent.getStudName());
        holder.studentRoll.setText(currentStudent.getStudRoll());

    }
    @Override
    public int getItemCount() {
        return studentList == null ? 0 : studentList.size();

    }
}

ACTIVITY

package com.pkg.attendanceapp;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;

import android.content.DialogInterface;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.view.View;
import android.widget.RadioGroup;
import android.widget.Toast;

import com.google.android.gms.tasks.Task;
import com.google.android.material.card.MaterialCardView;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.textview.MaterialTextView;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;

public class takeAttendance extends AppCompatActivity {

    DatabaseReference AttendanceDatabaseReference;
    private RecyclerView recyclerView;
    private RecyclerViewAdapter recyclerViewAdapter;
    public ArrayList<StudentList> studentListArray;
    //private String date = new SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()).format(new Date());

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

        //FloatingActionButton saveBtn = findViewById(R.id.floatingActionButton);
        recyclerView = findViewById(R.id.mRecyclerView);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setHasFixedSize(true);
        recyclerViewAdapter = new RecyclerViewAdapter(studentListArray);
        recyclerView.setAdapter(recyclerViewAdapter);
        studentListArray = new ArrayList<>();



        AttendanceDatabaseReference = FirebaseDatabase.getInstance().getReference("studentsInfo");
        AttendanceDatabaseReference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull final DataSnapshot dataSnapshot) {

                findViewById(R.id.progressBar).setVisibility(View.GONE);

                for (DataSnapshot mDataSnapshot : dataSnapshot.getChildren()){
                    StudentList studentsList = mDataSnapshot.getValue(StudentList.class);
                    studentListArray.add(studentsList);
                }

                recyclerViewAdapter = new RecyclerViewAdapter(studentListArray);
                recyclerView.setAdapter(recyclerViewAdapter);

            }
            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

                // Toast.makeText(takeAttendance.this, "Oops! Something Went Wrong...", Toast.LENGTH_LONG).show();
            }
        });
    }
 }

2 Answers2

0

I faced this problem earlier and the solution is that you have to save the boolean value of every checkbox in your model class, true if it is checked or false if not.

MojoJojo
  • 783
  • 5
  • 15
0

Based on other Posts/Guides, this is how it works -

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

private ArrayList<StudentList> studentList;
private ArrayList<String> mRollNum;
private Activity activity;
private OnCheckBoxClickListener mListener;

private SparseBooleanArray itemStateArray = new SparseBooleanArray();

public interface OnCheckBoxClickListener {

    void onCheckBoxClick(int position, boolean isChecked);
}

void setOnCheckBoxClickListener(OnCheckBoxClickListener listener){

    mListener = listener;
}

 class ViewHolder extends RecyclerView.ViewHolder {

    private MaterialTextView studentName;
    private MaterialTextView studentRoll;
    private MaterialTextView attendanceStatus;
    MaterialCheckBox mCheckbox;

    ViewHolder(@NonNull View itemView, final OnCheckBoxClickListener listener) {
        super(itemView);

        studentName = itemView.findViewById(R.id.stdName);
        studentRoll = itemView.findViewById(R.id.stdRoll);
        attendanceStatus = itemView.findViewById(R.id.studentAttendance);
        mCheckbox = itemView.findViewById(R.id.checkBox);

        mCheckbox.setOnClickListener(new View.OnClickListener() {
            @SuppressLint("SetTextI18n")
            @Override
            public void onClick(View view) {

                int adapterPosition = getAdapterPosition();
                if (!itemStateArray.get(adapterPosition, false)) {
                    attendanceStatus.setTextColor(Color.GREEN);
                    attendanceStatus.setText("Present");
                    mCheckbox.setChecked(true);
                    itemStateArray.put(adapterPosition, true);
                    listener.onCheckBoxClick(adapterPosition, true);

                }
                else  {
                    mCheckbox.setChecked(false);
                    itemStateArray.put(adapterPosition, false);
                    listener.onCheckBoxClick(adapterPosition, false);
                    attendanceStatus.setTextColor(Color.RED);
                    attendanceStatus.setText("Absent");


                }


            }
        });
    }

    @SuppressLint("SetTextI18n")
    void bind(int position) {

        if (!itemStateArray.get(position, false)) {
            mCheckbox.setChecked(false);
            attendanceStatus.setTextColor(Color.RED);
            attendanceStatus.setText("Absent");

        }
        else {
            attendanceStatus.setTextColor(Color.GREEN);
            attendanceStatus.setText("Present");
            mCheckbox.setChecked(true);

        }
    }
}

RecyclerViewAdapter(Activity activity, ArrayList<StudentList> mStudentList, ArrayList<String> rollNum ) {
    studentList = mStudentList;
    this.activity = activity;
    this.mRollNum = rollNum;

}

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

    View studentListView = LayoutInflater.from(parent.getContext())
            .inflate(R.layout.card_view, parent, false);

    return new ViewHolder(studentListView, mListener);
}

@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {

    StudentList currentStudent = studentList.get(position);

    holder.studentName.setText(currentStudent.getStudName());
    holder.studentRoll.setText(currentStudent.getStudRoll());

    holder.bind(position);
}

@Override
public int getItemCount() {
    return studentList == null ? 0 : studentList.size();
}