2017-01-24 6 views
4

Я пишу приложение Android, в котором есть элемент ListView с элементами CheckedTextView. В основном это вопрос с переменным количеством ответов. Если вы выберете один ответ, вы можете нажать «Далее» и посмотреть следующий вопрос.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 происходит OnStart):

/** 
    * 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> 
+0

Никто? Это довольно сложная проблема. Я пробовал его с пользовательскими галочками, но не повезло. – Ventis

+0

Отметьте это сообщение [setItemChecked not working?] (Http://stackoverflow.com/questions/7384505/setitemchecked-int-position-boolean-value-not-working), посмотрите, помогает ли он. – blizzard

+0

Дело в том, что оно действительно работает. Однако он не выводит галочку до тех пор, пока представление не будет «обновлено» чем-то вроде перетаскивания строки состояния над приложением. – Ventis

ответ

3

Я думаю, вы должны вызвать notifyDataSetChanged() после установки ответа на истинный, так что ListView может обновить свои взгляды немедленно

int pos = mAnswerAdapter.getPosition(selectedAnswer); 
if(pos != -1) { 
    listAnswers.setItemChecked(pos, true); 
    mAnswerAdapter.notifyDataSetChanged() 
} 
+0

Не имеет значения. Все-таки такое же поведение. – Ventis

+0

Извините, что я неправильно понял вопрос, я думал, что вид проверяется в адаптере, а listAnswers - это набор данных – lelloman

0

У меня были проблемы с интерфейсом при использовании таких вещей, как радиокнопки. Пройдите по логическому значению к 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(); 
} 

I надеюсь, это поможет

+0

Это не работает. Установка CheckedTextView для проверки в getView по-прежнему не отображает его при обновлении адаптера. Рисование radobutton onClick отлично работает, но рисовать его, когда вы выбираете элемент программно, нет. – Ventis

0

Я не помню, так как я не использовал ListView для списков на некоторое время. Если вы используете RecyclerView, и привязываете это с помощью onBindViewHolder к адаптеру, эквивалентный метод ListView должен делать трюк. Но RecyclerView - superior в Listview.

Поле Creata с именем selectedPosition, например, внутри класса адаптера. При вызове метода 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, и вид изменится по мере его изменения, когда будет выбран.

2

Для простого флажка, будет использоваться кнопка атрибута:

Android: кнопка = "@ вытяжка/questionnaire_answer_radio"

А для CheckedTextView использовать атрибут галочка:

android: checkMark = "@ drawable/questionnaire_answer_radio"