2014-02-10 4 views
0

저는 Android에 익숙하지 않아 현재 사용자 지정 목록 어댑터를 사용하는 데 문제가 있습니다.ListAdapter는 스크롤 할 때 이미 표시된 항목을 표시합니다.

기본적으로 각 질문 (라디오, 체크 박스, 텍스트, 숫자)마다 다른 유형의 질문 목록을 만들고 싶습니다. listview가 생성되면 정상적으로 표시됩니다. 하지만 아래로 스크롤하면 맨 아래의 항목이 다시 생성됩니다.

내 코드는 다음과 같다 :

public View getView(int position, View convertView, ViewGroup parent) { 

    View someView = convertView; 

    //get question type 
    String type = questions.get(position)[2]; 

    //declare viewholder 
    final ViewHolder holder; 
    Log.i("Position", Integer.toString(position)); 

    if (someView == null) { 
    Log.i("convertView", "null"); 
    holder = new ViewHolder(); 

    LayoutInflater inflater = (LayoutInflater) context 
       .getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
    someView = inflater.inflate(R.layout.list_survey, parent, false); 

    TextView textView = (TextView) someView.findViewById(R.id.surveyQuestion); 
    textView.setText(questions.get(position)[1]); 

    LinearLayout optionContainer = (LinearLayout) someView.findViewById(R.id.surveyOption); 

    int size = options.get(position).size(); 

    //radio button 
    if (type.equals("radio")) { 

     RadioGroup group = new RadioGroup(this.context); 
     RelativeLayout.LayoutParams groupParam = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT); 
     optionContainer.addView(group, groupParam); 
     RadioButton radio = null; 

     ArrayList<RadioButton> radios = new ArrayList<RadioButton>(); 

     for (int i=0; i<size; i++){ 
      radio = new RadioButton(this.context); 
      radio.setId(i+1); 
      radio.setText(options.get(position).get(i)[1]); 
      group.addView(radio); 
      radios.add(radio); 
     }  
     group.setOnCheckedChangeListener(new OnCheckedChangeListener() 
     { 
      public void onCheckedChanged(RadioGroup group, int checkedId) { 
       //Model element = (Model)group; 
      } 
     }); 

     holder.radiogroup = group; 
     holder.radiobuttons = radios; 

    //checkbox 
    } else if (type.equals("check")) { 
     CheckBox checkbox = null; 

     ArrayList<CheckBox> checks = new ArrayList<CheckBox>(); 

     for (int i=0; i<size; i++){ 
      checkbox = new CheckBox(this.context); 
      checkbox.setId(i+1); 
      checkbox.setText(options.get(position).get(i)[1]); 
      optionContainer.addView(checkbox); 
      checks.add(checkbox); 
     } 

     holder.checkboxes = checks; 

    //textfield 
    } else if (type.equals("txt")) { 
     EditText field = null; 

     ArrayList<EditText> fields = new ArrayList<EditText>(); 

     for (int i=0; i<size; i++){ 
      field = new EditText(this.context); 
      field.setId(i+1); 
      field.setHint(options.get(position).get(i)[1]); 
      optionContainer.addView(field); 
      fields.add(field); 
     } 

     holder.edittext = fields; 
    //numeric 
    } else if (type.equals("num")) { 
     EditText field = null; 

     ArrayList<EditText> fields = new ArrayList<EditText>(); 

     for (int i=0; i<size; i++){ 
      field = new EditText(this.context); 
      field.setId(i+1); 
      field.setHint(options.get(position).get(i)[1]); 
      field.setInputType(InputType.TYPE_CLASS_NUMBER); 
      optionContainer.addView(field); 
      fields.add(field); 
     } 

     holder.edittext = fields; 
    } 

    someView.setTag(holder); 

    } else { 
    Log.i("convertView", "not null"); 
    holder = (ViewHolder) someView.getTag(); 
    } 


    return someView; 
} 

viewHolder 클래스는 여기에 있습니다 : 내가 잘못 뭐하는 거지

//viewHolder 
static class ViewHolder { 
    ArrayList<CheckBox> checkboxes; 
    ArrayList<EditText> edittext; 
    RadioGroup radiogroup; 
    ArrayList<RadioButton> radiobuttons;  
} 

?

정말 고맙습니다. 다른 솔루션을 검색했지만 내 코드에서 작동하지 않습니다. 잘못 convertViewViewHolder을 사용하고 있기 때문에

감사

+0

** ** 첫 번째 항목은 무엇입니까? 커스텀'ArrayAdapter' 인스턴스를 어떻게 만들고 있습니까? – nKn

+0

아, 미안하지만, 나는 처음 발견 한 것만 알았지 만, 나는 당신의 게시물을보고 다시 확인했다. 분명히 스크롤 할 때마다 화면 밖으로 나온 항목이 불러 와서 목록에 있어야 할 다음 항목을 바꿉니다. – alfa

+0

그러면 @ LukaCiko의 대답은 정확합니다. 태그를 관리하는 것 뿐이므로'ViewHolder' 내부에서'View'를 업데이트하지 않습니다. – nKn

답변

3

이 일어났다. 아래로 스크롤하면 뷰가 재활용되고 converView은 null이되지 않습니다. ViewHolder 패턴은 일반적으로 이러한 방식으로 사용된다 :

public View getView(int position, View convertView, ViewGroup parent) { 
    if(convertView == null) { 
     inflate the view 
     create a ViewHolder and store the necessary views in it 
     use setTag to store the ViewHolder in the convertView 
    } 
    else { 
     use getTag to get the ViewHolder 
    } 
    update the views // <- you are not doing this when convertView != null 
} 

사용 convertView/ViewHolder 패턴 목록의 뷰가 대개 같은 레이아웃 있지만에 도시 된 다른 데이터를 가지고 있다는 것을 이유. 본질적으로 convertView (null이 아닌 경우)은 이전에 목록에서 사용 된 뷰이므로이 위치에 대한 올바른 데이터를 표시하도록 변환해야합니다. 그것을 재사용함으로써 값 비싼 레이아웃 인플레이션을 피할 수 있습니다. ViewHolder은 값 비싼 findViewById 호출을 피하기위한 추가 최적화 기능입니다.

+0

'비싼 findView 호출''id '로'ViewGroup'에서'View'를 찾는 것이 얼마나 비쌉니까? 그것은 단순한 반복입니다 ... – gunar

+0

글쎄 그것은 그렇게 보일 것입니다 만,'ViewGroup' 계층을 재귀 적으로 횡단해야합니다. 내 경험에 비추어 볼 때 "ViewHolder' 최적화는 눈에 띄는 효과가 있습니다. – LukaCiko

+0

나는 당신의 설명에서 기본 개념을 이해하지만, 나는 그것이 작동하도록하기 위해 무엇을해야하는지에 대해 아직도 명확하지 않다. 보기 업데이트는 무엇을 의미합니까? if 문에서 뷰를 생성하는 코드를 사용해야합니까? 그렇다면 상태를 viewHolder에 저장하려면 if 문 안에 무엇을 넣어야합니까? – alfa