CustomAdapter - CheckedTextView

У меня проблема с "запоминанием" состояний флажков в CheckTextView. Теперь, когда я нажимаю, он меняет состояние, но на другом CheckBox.

class CustomAdapterSmartwatch extends ArrayAdapter<String> {


static class ViewHolder {
    protected CheckedTextView cTextView;
}

ViewHolder holder;


public CustomAdapterSmartwatch(Context context, ArrayList<String> variables) {
    super(context,R.layout.row_smartwatch_resources,variables);
}

@NonNull
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        holder = new ViewHolder();
        LayoutInflater smartwatchinflater = LayoutInflater.from(getContext());
        convertView = smartwatchinflater.inflate(R.layout.row_smartwatch_resources,parent,false);
        holder.cTextView = (CheckedTextView) convertView.findViewById(R.id.row_smartwatch_checked);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    holder.cTextView.setText(getItem(position));

    holder.cTextView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if (holder.cTextView.isChecked()) {
                holder.cTextView.setChecked(false);
            } else {
                holder.cTextView.setChecked(true);
            }
        }
    });

    return convertView;
}

}

Сейчас я пытаюсь разобраться с использованием Holder, но я слышал, что можно использовать SparseBooleanArray. Может кто-нибудь объяснить, как заставить это работать?

РЕДАКТИРОВАТЬ 1 Хорошо, у меня есть ListView, который контролируется CustomAdapter. Этот адаптер содержит только 1 элемент (CheckedTextView). Проблема в том, что после прокрутки эти флажки не запоминают их состояние. Я видел ваш ответ с объяснением, но теперь после нажатия любого "CheckedTextView" состояние их флажка не меняется.

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

    @NonNull
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    if (convertView == null) {
        holder = new ViewHolder();
        LayoutInflater smartwatchinflater = LayoutInflater.from(getContext());
        convertView = smartwatchinflater.inflate(R.layout.row_smartwatch_resources,parent,false);
        holder.cTextView = (CheckedTextView) convertView.findViewById(R.id.row_smartwatch_checked);
        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    holder.cTextView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.d("MainActivity","Position = " + position);
            CheckedTextView checkedText = (CheckedTextView) v;
            checkedState.put(position, !checkedText.isChecked());

            Log.d("MainActivity","State = " + checkedState.get(position));

        }
    });

    holder.cTextView.setText(getItem(position));
    holder.cTextView.setChecked(checkedState.get(position));

    return convertView;
}

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

class CustomAdapterSmartwatch extends ArrayAdapter<String> {

public SparseBooleanArray checkedState = new SparseBooleanArray();
private CheckedTextView cTextView;


public CustomAdapterSmartwatch(Context context, ArrayList<String> variables) {
    super(context,R.layout.row_smartwatch_resources,variables);
}

@NonNull
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
    LayoutInflater smartwatchinflater = LayoutInflater.from(getContext());
    convertView = smartwatchinflater.inflate(R.layout.row_smartwatch_resources,parent,false);
    cTextView = (CheckedTextView) convertView.findViewById(R.id.row_smartwatch_checked);

    cTextView.setText(getItem(position));
    cTextView.setChecked(checkedState.get(position));

    cTextView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Log.d("MainActivity","Position = " + position);
            CheckedTextView checkedText = (CheckedTextView) v;
            checkedText.toggle();

            if (checkedText.isChecked())
                checkedState.put(position,true);
            else
                checkedState.delete(position);
            Log.d("MainActivity","State = " + checkedState.get(position));

        }
    });
    return convertView;
}

}

3 ответа

Решение

Вы должны сохранять логический флаг для каждого CheckTextView. Это может быть массив, список или SparseBooleanArray. Выбранная вами структура данных должна быть областью вашего адаптера:

class CustomAdapterSmartwatch extends ArrayAdapter<String> {
    private SparseBooleanArray checkedState = new SparseBooleanArray();

    // ...
}

Вы не хотите помещать его в держатель, потому что держатель удаляется только из видимых рядов. С другой стороны, вы хотите сохранить проверенное состояние для каждой строки, видимой или нет.

Теперь вы устанавливаете сохраненное проверенное состояние, когда пользователь нажимает на CheckedTextView:

@NonNull
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // ...

    holder.cTextView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            CheckedTextView checkedText = (CheckedTextView)v;
            checkedState.put(position, checkedText.isChecked());
        }
    });
}

И вы восстанавливаете проверенное состояние всякий раз, когда вы раздуваете представление или повторно используете его из держателя:

@NonNull
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    // ...

    holder.cTextView.setText(getItem(position));
    holder.cTextView.setChecked(checkedState.get(position));

    // ...
}

Вы можете просто использовать представление в самом методе onClick().

holder.cTextView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            if(v instanceOf CheckedTextView) {
                CheckedTextView c = (CheckedTextView) v;
                c.setChecked(!c.isChecked());
            }
        }
    });

Замените ваш код следующим обновлением:

class CustomAdapterSmartwatch extends ArrayAdapter<CustomAdapterSmartwatch.MyPojo> {

    class MyPojo {
        boolean checked;
        String data;

        public boolean isChecked() {
            return checked;
        }

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

        public String getData() {
            return data;
        }

        public void setData(String data) {
            this.data = data;
        }
    }

    static class ViewHolder {
        protected CheckedTextView cTextView;
    }

    ViewHolder holder;


    public CustomAdapterSmartwatch(Context context, ArrayList<MyPojo> variables) {
        super(context, R.layout.row_smartwatch_resources, variables);
    }

    @Nullable
    @Override
    public MyPojo getItem(int position) {
        return super.getItem(position);
    }

    @NonNull
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        if (convertView == null) {
            holder = new ViewHolder();
            LayoutInflater smartwatchinflater = LayoutInflater.from(getContext());
            convertView = smartwatchinflater.inflate(R.layout.row_smartwatch_resources,parent,false);
            holder.cTextView = (CheckedTextView) convertView.findViewById(R.id.row_smartwatch_checked);
            convertView.setTag(holder);
        } else {
            holder = (ViewHolder) convertView.getTag();
        }

        final MyPojo item = getItem(position);

        holder.cTextView.setText(item.getData());
        holder.cTextView.setChecked(item.isChecked());

        holder.cTextView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean nextStatus = !item.isChecked();
                item.setChecked(nextStatus);
                holder.cTextView.setChecked(nextStatus);
            }
        });

        return convertView;
    }
}
Другие вопросы по тегам