Включение Android switch в 1-м пункте продажи автоматически включает 10-й переключатель в recyclerview

#android #android-recyclerview #android-switch

#Android #android-recyclerview #android-переключатель

Вопрос:

Я работаю над приложением, в котором я извлек некоторые данные с сервера в recyclerview. Мой макет списка recyclervew содержит 3 вида [ textview (для отображения названия события), значок редактирования (для редактирования имен), один переключатель для включения / выключения событий. После нескольких дней работы я обнаружил странную проблему в этом модуле, т.Е. когда я включаю 1-й pos-коммутатор, я автоматически включаю 10-й переключатель в recyclerview, если имен меньше 10, скажем, если 9, то все переключатели работают нормально, затем при вводе 10-го они действуют, как указано, и поэтому при включении 2-го включается 11-й. Это похоже на то, что recylerview занимает 10-ю позицию как 1-я и так далее.

Я знаю, это странно, но, должно быть, проблема с положением или что-то в этом роде. Я погуглил, но ничего не смог найти по этому поводу. Я публикую код моего адаптера / списка item.xml . если вам понадобится что-либо еще, я опубликую это позже.

::::eventAdapter.java::::

 public class eventAdapter extends RecyclerView.Adapter<eventAdapter.UsersViewHolder> {

    Context context;
    List<EventModel> userListResponseData;

    public eventAdapter(Context context, List<EventModel> userListResponseData) {
        this.userListResponseData = userListResponseData;
        this.context = context;

    }

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

        View view = LayoutInflater.from(context).inflate(R.layout.event_list_items, parent,false);
        UsersViewHolder usersViewHolder = new UsersViewHolder(view);
        return usersViewHolder;
    }

    @Override
    public void onBindViewHolder(final UsersViewHolder holder, final int position) {
        // set the data
        final String eventName = userListResponseData.get(position).getEvent_name();
         holder.ed_eventname.setText(eventName);



        holder.ic_event_edit.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
              FragmentActivity activity = (FragmentActivity)(context);
              FragmentManager fm = activity.getSupportFragmentManager();
              EditEvent_Dialog alertDialog = new EditEvent_Dialog();
              Bundle bundle = new Bundle();
              bundle.putString("event_name", eventName);
              alertDialog.setArguments(bundle);

              alertDialog.show(fm, "fragment_alert");
//
          }
      });

    holder.event_cardView.setOnClickListener(new View.OnClickListener() {
                      @Override
                      public void onClick(View v) {
                          boolean state=holder.EventSwitch.isChecked();
                          if (state){

                              Toast.makeText(context, eventName " is Activated", Toast.LENGTH_SHORT).show();
                          }
                          else
                              Toast.makeText(context, eventName " is Deactivated", Toast.LENGTH_SHORT).show();
                          }
                  });
          }

    @Override
    public int getItemCount() {
        return userListResponseData.size(); // size of the list items
    }

    class UsersViewHolder extends RecyclerView.ViewHolder {
        // init the item view's
        private TextView ed_eventname;
        private ImageView ic_event_edit;
        private Switch EventSwitch;
        private CardView event_cardView;

        public UsersViewHolder(View itemView) {
            super(itemView);
            // get the reference of item view's
            ed_eventname = (TextView) itemView.findViewById(R.id.fetchevent_name);
            ic_event_edit = (ImageView) itemView.findViewById(R.id.edit_event);
            EventSwitch = (Switch) itemView.findViewById(R.id.event_switch);
            event_cardView = (CardView) itemView.findViewById(R.id.event_list_card);
        }
    }
}
  

::::event_list_items.xml::::

 <?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@ id/event_list_card"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_margin="10dp"
    card_view:cardBackgroundColor="@color/colorPrimary"
    card_view:cardCornerRadius="10dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:background="@color/colorPrimary">

        <TextView
        android:id="@ id/fetchevent_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#fff"
        android:layout_gravity="left|center"
        android:padding="5dp"
        android:textSize="15sp"
        android:layout_margin="5dp"
        />
        <ImageView
            android:id="@ id/edit_event"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/pencilicon"
            android:layout_margin="5dp"
            android:layout_gravity="center"

            android:padding="5dp"/>
        <Switch
            android:id="@ id/event_switch"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="5dp"
            android:layout_gravity="end|center"
            android:theme="@style/SwitchCompatTheme" />
    </LinearLayout>
</android.support.v7.widget.CardView>
  

:::: Recyclerview в основном макете ::::

  <android.support.v7.widget.RecyclerView
        android:id="@ id/recyclerView_event"
        android:scrollbars="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
  

:::: РЕДАКТИРОВАТЬ::::

EventModel.java

 public class EventModel {

    public String event_name;

    public EventModel(String event_name){
        this.event_name = event_name;
    }

    public EventModel(){

    }

    public void setEvent_name(String event_name) {
        this.event_name = event_name;
    }

    public String getEvent_name() {
        return event_name;
    }
}
  

Комментарии:

1. Пожалуйста, укажите для нас EventModel класс, я помогу вам больше

2. Хорошо, позвольте мне отредактировать вопрос @AlanDeep

3. @AlanDeep пожалуйста, проверьте

4. Хорошо, еще один момент, когда вы переключаете переключатель? когда вы также нажимаете на cardview?

5. Нет, при просмотре карты он только сообщает, активен он или нет, переключается только при перенастройке переключателя

Ответ №1:

Проблема здесь в том, что вы проверяете, установлен ли переключатель в представлении, а не в модели. В модели должна быть отмечена логическая переменная IsChecked, которая определяет, проверено представление или нет. Вы никогда не должны проверять, проверено ли представление из представления. Например,

Добавьте это в свой onBindViewHolder:

  holder.EventSwitch.setOnClickListener(new View.OnClickListener() {
                      @Override
                      public void onClick(View v) {
                          boolean state=userListResponseData.get(position).isChecked();
                          userListResponseData.get(position).setChecked(!state);

                  });
          }


      holder.EventSwitch.setChecked(userListResponseData.get(position).isChecked());
  

И измените свою модель на следующую:

  public class EventModel {

        public String event_name;

        private boolean checked;

        public boolean isChecked(){
            return checked;
        }
        public void setChecked(boolean checked){
            this.checked = checked;

        }
        public EventModel(String event_name){
            this.event_name = event_name;
        }

        public EventModel(){

        }

        public void setEvent_name(String event_name) {
            this.event_name = event_name;
        }

        public String getEvent_name() {
            return event_name;
        }


}
  

Комментарии:

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

2. вы имеете в виду, что я должен создать функцию в моем классе модели, а затем она должна ее проверить?

3. да, условия не создают никаких проблем, даже если я удалил их все, он ведет себя одинаково во внешнем интерфейсе.

4. @GabeSechan да, он boolean state=holder.EventSwitch.isChecked();

5. эй, брат, спасибо за помощь, теперь он работает очень хорошо

Ответ №2:

Это связано с переработкой просмотра (из названия класса). Представления используются повторно и привязываются к новым значениям по мере прокрутки списка. Чтобы это сработало, ваша функция bind ДОЛЖНА устанавливать состояние проверки при каждом ее вызове. И вашим прослушивателям проверки необходимо где-то записать состояние проверки в класс модели, поэтому, если вы прокрутите эту позицию с экрана, а затем снова включите, вы сможете ее восстановить.

Весь смысл recycler view заключается в том, чтобы добиться такого поведения при переработке, чтобы вы могли минимизировать использование памяти в представлениях (которые очень тяжелые). Это не просто отображение объектов в списке. Похоже, вы не поняли, как работает класс.

Комментарии:

1. привет, спасибо за ответ, и да, я немного понимаю поведение recyclerview, но я думал, что это сработает, но это не сработало. Не могли бы вы, пожалуйста, рассказать мне подробнее о thins и о том, как я могу заставить это работать.

2. По сути, ваш onBindViewHolder должен установить ВСЕ, что может быть изменено пользователем или приложением при каждом его вызове. Все остальное приведет к ошибкам, которые вы видите в вашем. Это означает, что состояние checked должно устанавливаться при каждом вызове onBindViewHolder. И, как я уже говорил, вашему прослушивателю кликов необходимо сохранить это состояние, чтобы вы могли восстановить его при прокрутке назад (или вы потеряете его, если прокрутите за пределы экрана).

3. хорошо, вы имеете в виду, что я должен сохранять состояния при каждом изменении проверки, чтобы я мог использовать их при перезагрузке страницы?

4. Страница не только перезагружается, но и прокручивается. При прокрутке, если на экране 10 просмотров, тот же самый параметр используется для индекса 0, 10, 20 и т.д. Если вы хотите, чтобы значение было правильным при прокрутке назад, вам нужно сохранить их где-нибудь в модели

5. хорошо, я понимаю это больше, чем когда-либо, но у меня есть вопрос, в соответствии с текущей ситуацией, если toogle 1-й переключатель сохранит его в серверной части через некоторые вызовы методов, не сохранит ли это также 10-й переключатель? или это будет работать так, как при сохранении, я буду вызывать метод только для 1-го переключателя, например `model.get (position).setState («true»)`????