Выбор одного из значения радиогруппы и прокрутка вниз и некоторый элемент, выбранный автоматически в представлении Recycler (новичок) - PullRequest
4 голосов
/ 19 января 2020

Я делаю систему посещаемости, где я беру посещаемость с помощью RadioGroup с двумя вариантами. Когда я выбираю какую-нибудь радиокнопку и прокручиваю вниз, некоторые другие радиокнопки выбираются автоматически. Если я изменю их, верхние тоже будут изменены. Я новичок, надеюсь, вы, ребята, можете помочь '

Основной класс

public class TeacherAttendanceActivity extends AppCompatActivity implements AttendanceAdapter.AttendanceAdapterListner {

    public static TeacherAttendanceActivity  teacherAttendanceActivity;
    private static final String TAG = TeacherAttendanceActivity.class.getSimpleName();

    List<AttendanceModel> listItems;
    private RecyclerView recyclerView;
    private RecyclerView.Adapter adapter;

    private AttendanceAdapter attendanceAdapter;
    ProgressDialog progressDialog;

    private SQLiteHandler db;
    private SessionManager session;

    private SearchView searchView;
    Button btnSubmit;
    JSONObject mainObj = new JSONObject();
    // date
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    String currentDateandTime = sdf.format(new Date());

    String class_id,title;
    Boolean Error;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_teacher_attendance);
        //get data from intent
        class_id = super.getIntent().getExtras().getString("id"); //class_id
        title = super.getIntent().getExtras().getString("title");
        getSupportActionBar().setTitle("Class: "+title+", Date: "+currentDateandTime );



        // SqLite database handler
        db = new SQLiteHandler(getApplicationContext());
        // session manager
        session = new SessionManager(getApplicationContext());

        btnSubmit=findViewById(R.id.buttonAttendanceSubmit);

        btnSubmit.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Error=false;
                Gson gson=new Gson();
                final String newDataArray=gson.toJson(listItems); // dataarray is list aaray

                    for (int i = 0; i < AttendanceAdapter.listItems.size(); i++){
                    if(AttendanceAdapter.listItems.get(i).getAttendance()==null){
                        Toast.makeText(TeacherAttendanceActivity.this, "Check attendance at roll:"+AttendanceAdapter.listItems.get(i).getRoll(), Toast.LENGTH_SHORT).show();
                        Error =true;
                        break;
                    }

                }
                if (!Error){
                    request(class_id,currentDateandTime,newDataArray);
                }

            }
        });


        listItems = new ArrayList<>();
        attendanceAdapter = new AttendanceAdapter(listItems, this, (AttendanceAdapter.AttendanceAdapterListner) this);

        recyclerView = (RecyclerView) findViewById(R.id.list_attendance);
        recyclerView.setLayoutManager(new LinearLayoutManager(TeacherAttendanceActivity.this));
        progressDialog = new ProgressDialog(this);

        teacherAttendanceActivity = this;
        //refresh_list(class_id);

    }

    @Override
    protected void onStart() {
        refresh_list(class_id);
        super.onStart();
    }

    @Override
    public void onAttendanceAdapterSelected(AttendanceModel model) {

    }
    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.refresh, menu);
        getMenuInflater().inflate(R.menu.tool_bar, menu);

        return true;
    }


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        switch (id){
            case R.id.action_settings:
                Toast.makeText(getApplicationContext(),"Sittings",Toast.LENGTH_LONG).show();
                return true;
            case R.id.action_logout:
                logoutUser();
                return true;
            case R.id.action_about:
                Toast.makeText(getApplicationContext(),"About",Toast.LENGTH_LONG).show();
                return true;
            case R.id.action_devinfo:
                Toast.makeText(getApplicationContext(),"Dev info",Toast.LENGTH_LONG).show();
                return true;
            case R.id.refresh:
                refresh_list(class_id);
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    void logoutUser() {
        session.setLogin(false);
        db.deleteUsers();
        // Launching the login activity
        Intent intent = new Intent(this, MainActivity.class);
        startActivity(intent);
        finish();
    }

    // refresh list
    public void refresh_list(String id) {
        // this method refresh list and get the json data
        listItems.clear();
        // adapter = new MyAdapter(listItems,getApplicationContext());
        recyclerView.setAdapter(attendanceAdapter);

        recyclerView.setItemAnimator(new DefaultItemAnimator());
        progressDialog.setMessage("Loading");
        progressDialog.show();

        StringRequest stringRequest = new StringRequest(Request.Method.GET, ApiConfig.URL_TEACHER_ATTENDANCE+id, new Response.Listener<String>() {
            @Override
            public void onResponse(String response) {
                progressDialog.dismiss();
                try {

                    progressDialog.hide();
                    JSONObject jsonObject = new JSONObject(response);
                    JSONArray jsonArray = jsonObject.getJSONArray("Data");  // finding data
                    Log.d(TAG, String.valueOf(jsonObject));

                    int len = jsonArray.length();
                    for (int i = 0; i < len; i++) {
                        JSONObject o = jsonArray.getJSONObject(i);
                        AttendanceModel item = new AttendanceModel(
                                o.getString("id"),
                                o.getString("name"),
                                o.getString("roll"),
                                o.getString("class_id"),
                                o.getString("status"),
                                null
                        );
                        listItems.add(item);

                        //adapter = new MyAdapter(listItems,getApplicationContext());
                        recyclerView.setAdapter(attendanceAdapter);   // setting them in list view

                    }
                } catch (JSONException e) {
                    e.printStackTrace();
                }
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                progressDialog.hide();
                Toast.makeText(TeacherAttendanceActivity.this, "Failed", Toast.LENGTH_SHORT).show();
            }
        }) {
            /** Passing some request headers* */
            @Override
            public Map getHeaders() throws AuthFailureError {

                SQLiteHandler db = new SQLiteHandler(getApplicationContext());
                HashMap<String,String> userDetail= db.getUserDetails();
                String userToken = userDetail.get("token");
                Log.d(TAG, String.valueOf(userToken));
                HashMap headers = new HashMap();
                headers.put("Accept", "application/json");
                headers.put("Authorization", "Bearer "+userToken);
                return headers;
            }
        };
        stringRequest.setShouldCache(false);
        VolleyRequest.getInstance(TeacherAttendanceActivity.this).addToRequestQueue(stringRequest);
    }

    // take attendance
    private void request( final String classId,final String date,final String data ) {

        progressDialog.setMessage("Taking attendance");
        showDialog();

        StringRequest strReq = new StringRequest(Request.Method.POST,
                ApiConfig.URL_TEACHER_ATTENDANCE_STORE, new Response.Listener<String>() {

            @Override
            public void onResponse(String response) {
                Log.d(TAG, "Login Response: " + response);
                hideDialog();
                try {
                    JSONObject jObj = new JSONObject(response);
                    boolean error = jObj.getBoolean("error");

                    // Check for error node in json
                    if (!error) {
                        String attendance = jObj.getString("Attendance");
                        Toast.makeText(TeacherAttendanceActivity.this, attendance, Toast.LENGTH_LONG).show();
                        finish();

                    } else {
                        // Error in login. Get the error message
                        String errorMsg = jObj.getString("message");
                        Toast.makeText(TeacherAttendanceActivity.this,
                                errorMsg, Toast.LENGTH_LONG).show();
                    }
                } catch (JSONException e) {
                    // JSON error
                    e.printStackTrace();
                    Toast.makeText(TeacherAttendanceActivity.this, "Json error: " + e.getMessage(), Toast.LENGTH_LONG).show();
                }

            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "Login Error: " + error.getMessage());
                Toast.makeText(TeacherAttendanceActivity.this,
                        error.getMessage(), Toast.LENGTH_LONG).show();
                hideDialog();
            }
        }) {

            /** Passing some request headers* */
            @Override
            public Map getHeaders() throws AuthFailureError {

                SQLiteHandler db = new SQLiteHandler(TeacherAttendanceActivity.this);
                HashMap<String,String> userDetail= db.getUserDetails();
                String userToken = userDetail.get("token");
                Log.d(TAG, String.valueOf(userToken));
                HashMap headers = new HashMap();
                headers.put("Accept", "application/json");
                headers.put("Authorization", "Bearer "+userToken);
                return headers;
            }

            @Override
            protected Map<String, String> getParams() {
                // Posting parameters to login url
                Map<String, String> params = new HashMap<String, String>();
                params.put("class_id", classId);
                params.put("date", date);
                params.put("data", data);

                return params;
            }

        };
        strReq.setShouldCache(false);
        // Adding request to request queue
        VolleyRequest.getInstance(TeacherAttendanceActivity.this).addToRequestQueue(strReq);
    }
    private void showDialog() {
        if (!progressDialog.isShowing())
            progressDialog.show();
    }

    private void hideDialog() {
        if (progressDialog.isShowing())
            progressDialog.dismiss();
    }


}

Модельный класс ' Модельный класс для удобства

1013

Класс адаптера Класс адаптера

public class AttendanceAdapter extends RecyclerView.Adapter<AttendanceAdapter.ViewHolder>  implements Filterable

{
    // date
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    String currentDateandTime = sdf.format(new Date());

    private static final String TAG = AttendanceAdapter.class.getSimpleName();


    public static List<AttendanceModel> listItems;
    private List<AttendanceModel> listItemsFiltered;
    private Context context;
    private ProgressDialog dialog;
    private AttendanceAdapter.AttendanceAdapterListner listner;

    private ProgressDialog pDialog;
    private SQLiteHandler db;
    public static JSONObject jo = new JSONObject();
    public static JSONArray ja  = new JSONArray();




    public AttendanceAdapter(List<AttendanceModel> listItems, Context context, AttendanceAdapter.AttendanceAdapterListner listner) {
        this.listItems = listItems;
        this.listner=listner;
        this.context = context;
        this.listItemsFiltered =listItems;

        // SqLite database handler
        db = new SQLiteHandler(context);

        // Progress dialog
        pDialog = new ProgressDialog(context);


    }

    @Override
    public Filter getFilter() {
        return new Filter() {
            @Override
            protected FilterResults performFiltering(CharSequence charSequence) {
                String charString = charSequence.toString();
                if (charString.isEmpty()) {
                    listItemsFiltered = listItems;
                } else {
                    List<AttendanceModel> filteredList = new ArrayList<>();
                    for (AttendanceModel row : listItems) {

                        // name match condition. this might differ depending on your requirement
                        // here we are looking for name or phone number match
                        if (row.getName().toUpperCase().contains(charSequence.toString().toUpperCase())||row.getName().toLowerCase().contains(charSequence.toString().toLowerCase())) {

                            filteredList.add(row);
                        }
                    }

                    listItemsFiltered = filteredList;
                }

                FilterResults filterResults = new FilterResults();
                filterResults.values = listItemsFiltered;
                return filterResults;
            }

            @Override
            protected void publishResults(CharSequence charSequence, FilterResults filterResults) {
                listItemsFiltered = (ArrayList<AttendanceModel>) filterResults.values;
                notifyDataSetChanged();
            }
        };
    }


    public class ViewHolder extends RecyclerView.ViewHolder {

        public TextView name;
        public TextView roll;
        public TextView previous;

        RadioGroup radioAttendance;
        RadioButton radioAttendancePresent,radioAttendanceAbsent;


        public CardView card_view;


        public ViewHolder(View itemView) {
            super(itemView);
            name= (TextView) itemView.findViewById(R.id.textViewAttendanceStudentName);
            roll = (TextView) itemView.findViewById(R.id.textViewAttendanceStudentRoll);
            previous = (TextView) itemView.findViewById(R.id.textViewAttendanceStudentPreviousStatus);
            radioAttendance = itemView.findViewById(R.id.radioAttendance);
            radioAttendancePresent =itemView.findViewById(R.id.radioAttendancePresent);
            radioAttendanceAbsent =itemView.findViewById(R.id.radioAttendanceAbsent);

            //card_view = (CardView) itemView.findViewById(R.id.class_card_view); // card view for on click method
            itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick( View view) {
                    // send selected contact in callback
                    listner.onAttendanceAdapterSelected(listItemsFiltered.get(getAdapterPosition()));  // selecting cardview and position (model)
                }
            });
            radioAttendance.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
                @Override
                public void onCheckedChanged(RadioGroup radioGroup, int i) {
                    //Toast.makeText(TeacherAttendanceActivity.this, toString(i), Toast.LENGTH_SHORT).show();
                    // Toast.makeText(context,"clicked at position"+i+" "+id+""+name,Toast.LENGTH_SHORT).show();

                    if(radioAttendancePresent.isChecked())
                    {
                        listItems.get(getAdapterPosition()).setAttendance("present");


                    }
                    else {
                        listItems.get(getAdapterPosition()).setAttendance("absent");

                    }

                }
            });


        }


    }


    @Override
    public AttendanceAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.attendance_list, parent, false);
        return new AttendanceAdapter.ViewHolder(v);
    }

    @Override
    public void onBindViewHolder  (final AttendanceAdapter.ViewHolder holder, final int position) {
        final AttendanceModel listItem = listItemsFiltered.get(position);

        holder.name.setText(listItem.getName());
        holder.roll.setText(listItem.getRoll());
        holder.previous.setText(listItem.getPreviousAttendance());


    }

    public interface AttendanceAdapterListner {
        void onAttendanceAdapterSelected(AttendanceModel model);  // sending cardview to say the dialoge and model for sending context
    }

    @Override
    public int getItemCount() {
        return listItemsFiltered.size();
    }

    private void showDialog() {
        if (!pDialog.isShowing())
            pDialog.show();
    }

    private void hideDialog() {
        if (pDialog.isShowing())
            pDialog.dismiss();
    }
}

Ответы [ 2 ]

2 голосов
/ 21 января 2020

Ваша проблема может быть решена путем внесения небольших изменений в ваш адаптер представления Recycler, пожалуйста, не отключайте свойство, пригодное для повторного использования, это заставляет ваш переработчик просматривать прославленное представление списка.

Я вижу, вы пытались использовать разреженный логический массив для хранения состояния переключателей, это хорошо, но вам это тоже не нужно. Идея использования логического массива Sparse состоит в том, чтобы сохранить состояние каждого элемента в представлении переработчика, чтобы при его повторной обработке у вас все еще была ссылка на состояние каждого элемента.

В вашем адаптере вы у нас уже есть что-то, что мы можем использовать, чтобы узнать состояние, то есть свойство attendance вашей модели, в этом случае вы можете установить состояние своих флажков, проверив, является ли свойство посещаемости present или absent.

Еще одна вещь, касающаяся вашего кода, заключается в том, что вы используете onCheckChangedListener в качестве обработчика события щелчка для своей радиокнопки, его не следует использовать, поскольку он реагирует на все события проверки измененных, даже если он запущен из кода, а не из действий пользователя, поэтому, когда вы связываете свое представление и устанавливаете любую из своих переключателей как отмеченные или не отмеченные, она вызывает этот обратный вызов.

Вот модифицированная версия вашего класса ViewHolder, которая решает эту проблему. вопрос, применяя решение выше.

 public class ViewHolder extends RecyclerView.ViewHolder {

    public TextView name;
    public TextView roll;
    public TextView previous;

    RadioGroup radioAttendance;
    RadioButton radioAttendancePresent, radioAttendanceAbsent;


    public CardView card_view;


    public ViewHolder(View itemView) {
        super(itemView);
        name = (TextView) itemView.findViewById(R.id.textViewAttendanceStudentName);
        roll = (TextView) itemView.findViewById(R.id.textViewAttendanceStudentRoll);
        previous = (TextView) itemView.findViewById(R.id.textViewAttendanceStudentPreviousStatus);
        radioAttendance = itemView.findViewById(R.id.radioAttendance);
        radioAttendancePresent = itemView.findViewById(R.id.radioAttendancePresent);
        radioAttendanceAbsent = itemView.findViewById(R.id.radioAttendanceAbsent);

        radioAttendancePresent.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                radioAttendancePresent.setChecked(true);
                listItems.get(getAdapterPosition()).setAttendance("present");
            }
        });

        radioAttendanceAbsent.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                radioAttendanceAbsent.setChecked(true);
                listItems.get(getAdapterPosition()).setAttendance("absent");
            }
        });

    }

    void bind(int position) {
        // use the sparse boolean array to check
        if (listItems.get(position).getAttendance() != null) {
            if (listItems.get(position).getAttendance().equals("present")) {
                radioAttendancePresent.setChecked(true);
            } else if (listItems.get(position).getAttendance().equals("absent")) {
                radioAttendanceAbsent.setChecked(true);
            }
        } else {
            radioAttendance.clearCheck();
        }

        name.setText(listItems.get(position).getName());
        roll.setText(listItems.get(position).getRoll());
        previous.setText(listItems.get(position).getPreviousAttendance());
    }
}

Обратите внимание, что у нас есть отдельный прослушиватель щелчков для каждой радиокнопки, мы устанавливаем состояние в списке элементов и просто проверяем это состояние, когда мы связываемся, также мы удалили onCheckChangedListener и разреженный логический массив, последнее, что мы убедились, что когда для свойства посещаемости не задано состояние, мы просто очищаем переключатели, чтобы никто не был выбран, и код стал намного проще и теперь работает правильно.

1 голос
/ 19 января 2020

Вы должны инициализировать RadioButton в зависимости от состояния модели, как показано ниже:

@Override
public void onBindViewHolder  (final AttendanceAdapter.ViewHolder holder, final int position) {
    final AttendanceModel listItem = listItemsFiltered.get(position);

    holder.name.setText(listItem.getName());
    holder.roll.setText(listItem.getRoll());
    holder.previous.setText(listItem.getPreviousAttendance());

    final String id =listItem.getId();
    final String class_id =listItem.getClassId();


    holder.radioAttendance.setOnCheckedChangeListener(null);
    if(listItem.getAttendance().equalsIgnoreCase("present")) {
        radioAttendancePresent.setChecked(true);
    } else {
        radioAttendancePresent.setChecked(false);
    }

    //Add listener here and remove from holder
    holder.radioAttendance.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
        @Override
        public void onCheckedChanged(RadioGroup radioGroup, int i) {
            if(holder.radioAttendancePresent.isChecked()) {
                listItemsFiltered.get(position).setAttendance("present");
            } else {
                listItemsFiltered.get(position).setAttendance("absent");
            }

            notifyDataSetChanged();
        }
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...