【问题标题】:Android ListView shows the list items in a dis-ordered mannerAndroid ListView 无序显示列表项
【发布时间】:2016-06-13 17:38:03
【问题描述】:

有时列表视图会重复前 5 个值,有时会重复 10 个值,但代码不会显示任何错误或警告。另一个问题是,如果我选择一个 RadioButton,它会更改具有相同 ID(但位置不同)的整个 RadioButtons

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.TextView;

import org.json.JSONObject;

import java.util.ArrayList;

/**
 * Created by Anu Martin on 3/1/2016.
 */
public class QuestionAdapter extends BaseAdapter{

    ArrayList<JSONObject> arrayList;
    LayoutInflater inflater;
    Context context;
    public static final String KEY_QUESTION_TYPE="type"
            ,KEY_QUESTION="Q"
            ,KEY_QESTION_OPTION_YES="OPTYES"
            ,KEY_QUESTION_OPTION_NO="OPTNO"
            ,KEY_QUESTION_OPTION1="OPT1"
            ,KEY_QUESTION_OPTION2="OPT2"
            ,KEY_QUESTION_OPTION3="OPT3"
            ,KEY_QUESTION_OPTION4="OPT4"
            ,KEY_QUESTION_EXPLANATION="EXPL"
            ,KEY_ARRAY_QUESTION="A";
    public static final int QUESTION_TYPE_YESORNO=15
            ,QUESTION_TYPE_MULTIPLE_CHOICE=20
            ,QUESTION_TYPE_SHORT_ANSWER=25;

    public QuestionAdapter(Context context,ArrayList<JSONObject> arrayList){
        this.arrayList=arrayList;
        this.context=context;
        inflater=LayoutInflater.from(this.context);
    }

    @Override
    public int getCount() {
        return arrayList.size();
    }

    @Override
    public Object getItem(int position) {
        return arrayList.get(position);
    }

    @Override
    public long getItemId(int position) {
        return 0;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        Log.e("getView",position+"");
        try {
            JSONObject jsonObject = this.arrayList.get(position);
            Log.d("getView",jsonObject.toString());
            int questionType=jsonObject.getInt(KEY_QUESTION_TYPE);
                switch (questionType){
                    case QUESTION_TYPE_YESORNO:{
                        ViewHolderYesOrNo mViewHolder;
                        if(convertView==null){
                            convertView=this.inflater.inflate(R.layout.row_question_yesorno,null);
                            mViewHolder=new ViewHolderYesOrNo(convertView);
                            convertView.setTag(mViewHolder);
                        }else{
                            mViewHolder=(ViewHolderYesOrNo)convertView.getTag();
                        }
                        mViewHolder.question.setText(jsonObject.getString(KEY_QUESTION));
                        mViewHolder.type.setText(jsonObject.getInt(KEY_QUESTION_TYPE)+"");

                        if(jsonObject.getString(KEY_QUESTION_EXPLANATION)!=null) {
                            mViewHolder.explanation.setText(jsonObject.getString(KEY_QUESTION_EXPLANATION));
                            mViewHolder.explanation.setVisibility(View.VISIBLE);
                        }
                    }break;
                    case QUESTION_TYPE_MULTIPLE_CHOICE:{
                        final ViewHolderMultipleChoice mViewHolder;
                        if(convertView==null){
                            convertView=this.inflater.inflate(R.layout.row_question_multiple_choice,null);
                            mViewHolder=new ViewHolderMultipleChoice(convertView);
                            convertView.setTag(mViewHolder);
                        }else{
                            mViewHolder=(ViewHolderMultipleChoice)convertView.getTag();
                        }
                        mViewHolder.question.setText(jsonObject.getString(KEY_QUESTION));
                        mViewHolder.type.setText(jsonObject.getInt(KEY_QUESTION_TYPE)+"");
                        mViewHolder.explanation.setText("");

                        mViewHolder.option1.setText(jsonObject.getString(KEY_QUESTION_OPTION1));
                        mViewHolder.option2.setText(jsonObject.getString(KEY_QUESTION_OPTION2));
                        mViewHolder.option3.setText(jsonObject.getString(KEY_QUESTION_OPTION3));
                        mViewHolder.option4.setText(jsonObject.getString(KEY_QUESTION_OPTION4));

                        if(jsonObject.getString(KEY_QUESTION_EXPLANATION)!=null) {
                            mViewHolder.explanation.setText(jsonObject.getString(KEY_QUESTION_EXPLANATION));
                            mViewHolder.explanation.setVisibility(View.VISIBLE);
                        }

                    }break;
                    case QUESTION_TYPE_SHORT_ANSWER:{
                        ViewHolderShortAnswer mViewHolder;
                        if(convertView==null){
                            convertView=this.inflater.inflate(R.layout.row_question_short_answer,null);
                            mViewHolder=new ViewHolderShortAnswer(convertView);
                            convertView.setTag(mViewHolder);
                        }else{
                            mViewHolder=(ViewHolderShortAnswer)convertView.getTag();
                        }
                        mViewHolder.question.setText(jsonObject.getString(KEY_QUESTION));
                        mViewHolder.type.setText(jsonObject.getInt(KEY_QUESTION_TYPE)+"");
                        if(jsonObject.getString(KEY_QUESTION_EXPLANATION)!=null) {
                            mViewHolder.explanation.setText(jsonObject.getString(KEY_QUESTION_EXPLANATION));
                            mViewHolder.explanation.setVisibility(View.VISIBLE);
                        }
                    }break;
                    default:{
                        if(convertView==null){
                            convertView=this.inflater.inflate(R.layout.row_question_not_available,null);
                        }
                    }
                }
            }catch (Exception e){

        }
        return convertView;
    }
    static class ViewHolderYesOrNo{
        public TextView question,type,explanation;
        public RadioGroup radioGroup;
        public RadioButton yes,no;

        public ViewHolderYesOrNo(View view){
            question=(TextView) view.findViewById(R.id.rowQuestionYesNo);
            type=(TextView)view.findViewById(R.id.rowQuestionType);
            explanation=(TextView)view.findViewById(R.id.rowQuestionExplanation);
            radioGroup=(RadioGroup)view.findViewById(R.id.rowOptionRadioGroup);

            yes=(RadioButton)view.findViewById(R.id.rowOptionYes);
            no=(RadioButton)view.findViewById(R.id.rowOptionNo);
        }
    }

    static class ViewHolderMultipleChoice{
        public TextView question,type,explanation;
        public RadioGroup radioGroup;
        public RadioButton option1,option2,option3,option4;

        public ViewHolderMultipleChoice(View view){
            question=(TextView) view.findViewById(R.id.rowQuestionYesNo);
            type=(TextView)view.findViewById(R.id.rowQuestionType);
            explanation=(TextView)view.findViewById(R.id.rowQuestionExplanation);
            radioGroup=(RadioGroup)view.findViewById(R.id.rowOptionRadioGroup);

            option1=(RadioButton)view.findViewById(R.id.rowOptionOne);
            option2=(RadioButton)view.findViewById(R.id.rowOptionTwo);
            option3=(RadioButton)view.findViewById(R.id.rowOptionThree);
            option4=(RadioButton)view.findViewById(R.id.rowOptionFour);
        }
    }

    static class ViewHolderShortAnswer{
        public TextView question,type,explanation;

        public ViewHolderShortAnswer(View view){
            question=(TextView) view.findViewById(R.id.rowQuestionYesNo);
            type=(TextView)view.findViewById(R.id.rowQuestionType);
            explanation=(TextView)view.findViewById(R.id.rowQuestionExplanation);
        }
    }
}

感谢您的帮助。

【问题讨论】:

    标签: android listview arraylist baseadapter


    【解决方案1】:

    正是这样的地方造成了你所看到的。

    if(jsonObject.getString(KEY_QUESTION_EXPLANATION)!=null) {
        mViewHolder.explanation.setText(jsonObject.getString(KEY_QUESTION_EXPLANATION));
        mViewHolder.explanation.setVisibility(View.VISIBLE);
    }
    

    简而言之,你忘记了 else 块。

    当你从你的视图中获得一个视图时,它仍然有之前设置的所有值。当只使用if部分而不使用else部分时,你只改变一些值,而其他保持不变。

    在这种情况下,当你的jsonObject没有KEY_QUESTION_EXPLANATION时,它会显示最后一项的解释,因此你需要添加

    else {
        mViewHolder.explanation.serVisibily(View.Invisible);//or Gone
    }
    

    编辑:

    粗体部分是导致您的问题的原因。流程是这样的:

    1. 您的适配器获得视图。起初,它是空的。
    2. 您的适配器检查空视图,如果它为空,它会创建一个新视图并设置一半的值(因为另一半是在 xml 中预设的)。
    3. 当您的视图变得不可见(屏幕外)并且需要新视图时,您的适配器会获取视图,该视图不为空。
    4. 您的适配器设置了一些值,未设置的值保留在以前的视图中。

    您可以使用我之前建议的 else 语句轻松解决此问题。

    【讨论】:

    • 感谢您的帮助。但是解释视图已经在行 xml 中设置了可见性,并且它工作正常。问题是在滚动列表视图时,列表顺序会自行更改并复制列表项。当点击列表项时自动触发所有具有相同 id 的列表项
    • 我可能还不够清楚。我会更新答案并澄清导致您的问题的原因。
    • 我以任何方式修复了它,感谢@MariusKaunietis,由于不可见视图导致的问题,
    猜你喜欢
    • 2017-02-17
    • 2013-01-08
    • 2012-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-09
    • 1970-01-01
    相关资源
    最近更新 更多