CheckedTextView не рисует галочку при программном выборе
Я пишу приложение для Android, в котором есть ListView с элементами CheckedTextView. Это в основном вопрос с переменным количеством ответов. Если вы выберете один ответ, вы можете нажать "Далее" и увидеть следующий вопрос.
Я написал весь код, чтобы сохранить ответы и перейти к следующим вопросам, а также предоставил пользователю "предыдущую" кнопку, чтобы вернуться к предыдущему вопросу. Если на предыдущий вопрос уже есть ответ, я хочу, чтобы этот ответ был выбран. И вот тут начинаются проблемы.
Прямо сейчас, я могу получить позицию выбранного ответа, и я звоню listView.setItemChecked(pos, true)
но переключатель не выбран.
if(selectedAnswer != null) {
int pos = mAnswerAdapter.getPosition(selectedAnswer);
if(pos != -1) {
listAnswers.setItemChecked(pos, true);
}
}
Только когда я делаю что-то еще, например, перетаскиваю строку состояния, вид, кажется, обновляется и рисует выбранное состояние радиокнопки.
Я заполняю список такими ответами:
mAnswerAdapter = new AnswerArrayAdapter(getContext(), R.layout.listitem_answer, currentQuestion.getAnswers(), user.getLanguage());
listAnswers.setAdapter(mAnswerAdapter);
mAnswerAdapter.notifyDataSetChanged();
Для справки:
Макет list_item:
<?xml version="1.0" encoding="utf-8"?>
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?attr/listPreferredItemHeightSmall"
android:drawableStart="@drawable/questionnaire_answer_radio"
android:drawablePadding="10dp"
android:gravity="center_vertical"
android:paddingStart="5dp"
android:paddingEnd="5dp"
android:textColor="@android:color/white"
android:id="@+id/questionnaire_answer_checkbox"/>
Адаптер:
package be.iminds.mresist;
import android.content.Context;
import android.support.annotation.NonNull;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckedTextView;
import java.util.List;
import be.iminds.mresist.models.QuestionnaireDefinition;
import butterknife.BindView;
import butterknife.ButterKnife;
public class AnswerArrayAdapter extends ArrayAdapter<QuestionnaireDefinition.Answer> {
private String mLang;
private Context mContext;
public AnswerArrayAdapter(Context context, int textViewResourceId, List<QuestionnaireDefinition.Answer> answers, final String lang) {
super(context, textViewResourceId, answers);
this.mContext = context;
this.mLang = lang;
}
@NonNull
@Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
AnswerArrayAdapter.ViewHolder holder = null;
QuestionnaireDefinition.Answer item = getItem(position);
if (convertView == null) {
convertView = inflater.inflate(R.layout.listitem_answer, parent, false);
holder = new AnswerArrayAdapter.ViewHolder(convertView);
convertView.setTag(holder);
} else
holder = (AnswerArrayAdapter.ViewHolder) convertView.getTag();
holder.answerText.setText(item.getAnswer(mLang));
return convertView;
}
static class ViewHolder {
@BindView(R.id.questionnaire_answer_checkbox) CheckedTextView answerText;
public ViewHolder(View view) {
ButterKnife.bind(this, view);
}
}
}
Соответствующий фрагмент кода (первый вызов openQuestion происходит при запуске):
/**
* Opens the question with the corresponding index
* @param questionIdx
*/
private void openQuestion(int questionIdx)
{
currentQuestionIdx = questionIdx;
final Question currentQuestion = getCurrentQuestion();
txtQuestionTitleCounter.setText(String.format(getString(R.string.questionnaire_counter), questionIdx + 1, qAssignment.getDefinition().getQuestions().size()));
txtQuestion.setText(currentQuestion.getQuestion(user.getLanguage()));
mAnswerAdapter = new AnswerArrayAdapter(getContext(), R.layout.listitem_answer, currentQuestion.getAnswers(), user.getLanguage());
listAnswers.setAdapter(mAnswerAdapter);
mAnswerAdapter.notifyDataSetChanged();
//If it's not the last question and there are more questions than one, make the next button visible
if(!isLastQuestion(currentQuestionIdx) && qAssignment.getDefinition().getQuestions().size() > 1)
mNextButton.setVisibility(View.VISIBLE);
else
mNextButton.setVisibility(View.GONE);
//If it's not the first question and there are more questions than one, make the previous button visible
if(!isFirstQuestion(currentQuestionIdx) && qAssignment.getDefinition().getQuestions().size() > 1)
mPreviousButton.setVisibility(View.VISIBLE);
else
mPreviousButton.setVisibility(View.GONE);
//If the question's already been answered, fill in the answer
markPreviousAnswer(currentQuestion);
}
/**
* Marks a previously selected answer
* @param currentQuestion
*/
private void markPreviousAnswer(Question currentQuestion) {
if(qAssignment.getAnswerValues() != null && qAssignment.getAnswerValues().containsKey(currentQuestion.getQuestionKey())) {
//Value of answer
Integer value = qAssignment.getAnswerValues().get(currentQuestion.getQuestionKey());
QuestionnaireDefinition.Answer selectedAnswer = null;
for(QuestionnaireDefinition.Answer answer: currentQuestion.getAnswers()) {
if(answer.getValue() == value) {
selectedAnswer = answer;
break;
}
}
if(selectedAnswer != null) {
int pos = mAnswerAdapter.getPosition(selectedAnswer);
if(pos != -1) {
listAnswers.setItemChecked(pos, true);
}
}
}
}
CheckedTextView селектор рисования:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_pressed="true">
<shape android:shape="oval">
<size android:width="16dp" android:height="16dp"/>
<solid android:color="@color/colorPrimaryDarker"/>
<stroke android:color="@android:color/white" android:width="2dp"/>
</shape>
</item><!-- pressed -->
<item android:state_checked="true">
<shape android:shape="oval">
<size android:width="16dp" android:height="16dp"/>
<solid android:color="@color/colorPrimaryDarker"/>
<stroke android:color="@android:color/white" android:width="2dp"/>
</shape>
</item> <!-- checked -->
<item>
<shape android:shape="oval" android:innerRadius="10dp">
<size android:width="16dp" android:height="16dp"/>
<stroke android:color="@android:color/white" android:width="1dp"/>
</shape>
</item> <!-- default -->
</selector>
4 ответа
Я думаю тебе следует позвонить notifyDataSetChanged()
после установки ответа на истину, чтобы ListView
может обновить свои взгляды немедленно
int pos = mAnswerAdapter.getPosition(selectedAnswer);
if(pos != -1) {
listAnswers.setItemChecked(pos, true);
mAnswerAdapter.notifyDataSetChanged()
}
Для простого флажка будет использоваться кнопка атрибута:
android:button="@drawable/questionnaire_answer_radio"
А для CheckedTextView используйте атрибут checkMark:
android:checkMark="@drawable/questionnaire_answer_radio"
У меня были похожие проблемы с интерфейсом при использовании таких вещей, как переключатели. Передайте логическое значение в getView, а затем в состояние getView, которое:
boolean checked; //The variable being passed
.
.
.
if(item.getBoolean){
radioButton.setChecked(true);
}
else
{
radioButton.setChecked(false);
}
Затем, когда кто-нибудь нажмет кнопку "Изменить", добавьте в функцию onClick кнопки radioButton следующее:
if(item.getBoolean){
item.setBoolean(false)
mAnswerAdapter.notifyDatasetChanged();
}
else
{
item.setBoolean(true)
mAnswerAdapter.notifyDatasetChanged();
}
надеюсь, это поможет
Я не помню, так как я некоторое время не использовал ListView для списков. Если вы используете RecyclerView, вы привязываете это с помощью onBindViewHolder к адаптеру, эквивалентный метод ListView должен сделать свое дело. Но RecyclerView превосходит Listview.
Поле Creata с именем selectedPosition, например, внутри класса Adapter. Когда вы вызываете notifyDatasetChanged
, onBindView
метод RecyclerView.Adapter вызывается. Проверьте положение, которое вы хотите выбрать, с помощью поля selectedPosition адаптера и измените представление в соответствии с этим положением.
public void onBindViewHolder(MyViewHolder holder, final int position) {
holder.tvCamMenu.setText(data.get(position));
if (selectedPosition == position) {
holder.tvCamMenu.setTextColor(Color.YELLOW);
} else {
holder.tvCamMenu.setTextColor(Color.WHITE);
}
}
Это фрагмент, который я использую, чтобы установить цвет выбранного столбца внутри горизонтального RecyclerView. Наконец позвони notifyDatasetChanged
и вид изменится, как вы измените его, чтобы быть при выборе.