2016-07-28 8 views
1

사용자 지정 어댑터가있는 ListView가 있으며 각 행에는 사용자가 설정할 수있는 검색 바가 들어 있습니다. 각 탐색 모음에는 어댑터에 설정된 seekBarChangeListener가 있으며 사용자가 ListView에서 검색 막대 값을 변경하면 어댑터의 arraylist가 업데이트됩니다. 이것은 내가 어댑터의 getView()에있어 무엇 : 스크롤 후 안드로이드 ListView가 값을 재설정하지 않게하려면 어떻게해야합니까?

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

    final ViewHolder viewHolder; 

    View v = convertView; 
    if(v == null){ 
     v = inflater.inflate(R.layout.row, null); 
     viewHolder = new ViewHolder(); 
     viewHolder.contentView = (TextView) v.findViewById(R.id.pref_content); 
     viewHolder.sliderView = (SeekBar) v.findViewById(R.id.pref_slider); 
     v.setTag(viewHolder); 
    }else{ 
     viewHolder = (ViewHolder) v.getTag(); 
    } 

    // Get initial values 
    Prompt p = promptList.get(position); 
    String content = p.getContent(); 
    int sliderLevel = p.sliderLevel(); 

    // Set views with initial values 
    viewHolder.contentView.setText(content); 
    viewHolder.sliderView.setMax(noOfLevels); 
    viewHolder.sliderView.setProgress(sliderLevel); 

    // Set Change Listener for Seekbar 
    viewHolder.sliderView.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { 
     @Override 
     public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 

      // Set new level of the Slider in the Array List 
      promptList.get(position).setSliderLevel(progress); 
     } 
    }); 

    return v; 
} 

그래서 사용자는 ChangeListener의이 ArrayList를에서 개체를 가져오고 새로운 sliderLevel 값을 설정하는 검색 막대의 값을 변경할 때. 그러나 ListView에서 새 값을 설정 한 다음 다시 위로 스크롤하여 getView가 다시 호출되면 seekListbar는 arrayList의 값을 변경했지만 초기 값으로 돌아갑니다.

누군가 내가 여기서 잘못 가고있는 것을 보여줄 수 있습니까? 감사합니다

+0

에게 설명 당신은 각 검색 막대의 값을 저장하기 위해 별도의 목록을 작성하고의 getView 방법에 해당하는 값으로 설정해야합니다. Listview는 뷰를 재활용합니다. – Chol

+0

ListView는 뷰를 재활용하지만 어댑터는 동일한 ArrayList를 유지합니다. 뷰가 재활용되면 getView()가 다시 호출되어 동일한 ArrayList에 액세스합니다. 따라서 ArrayList를 변경하면 getView()가 다시 호출되면 새로운 값이 표시됩니다. – Highway62

+0

예, 맞아요, 이상 해요. – Chol

답변

1

onProgressChanged()은 사용자가 SeekBar 값을 변경할 때마다 호출됩니다. 그러나 그것은 또한 "시스템에 의해"(나는 이것이 SeekBar가 convertView의 일부로 재활용되기 때문에 발생한다고 생각합니다)라고합니다. 이 fromUser 사실 여부를 확인하는 것이 필요하다 이유 : 귀하의 경우

@Override 
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 
    if (!fromUser) return; 

    // Set new level of the Slider in the Array List 
    promptList.get(position).setSliderLevel(progress); 
} 

, 당신은 여전히 ​​도시 한 SeekBar 특정 하나로 만 사용자가 진행 상황을 변경하기 때문에 notifyDatasetChanged()를 호출 할 필요가 없습니다. 사용자가 스크롤하기 때문에 숨겨지고이 위치에 대한 데이터가 나중에 다시 표시되어야하는 경우 getView()이 호출되고 정확한 값은 데이터를 표시하는 convertView의 SeekBar으로 설정됩니다.

다른 생각 (성능상의 이유) : 사용자가 슬라이더 조작을 중지하자마자 진행 값을 promptList.get(position)으로 변경하는 것을 고려하십시오. 이를 위해, 당신은 onStopTrackingTouch() 대신 onProgressChanged()의 덮어 쓸 수

promptList.get(position).setSliderLevel(seekBar.getProgress()); 
+0

위대한 설명, 고마워요. 나는 거의 동일한 솔루션을 사용하여 내 자신의 질문에 답변했지만,이 답변은 내 ListView에서 대부분의 문제를 일으키는 것으로 받아 들일 것입니다. 감사. – Highway62

0

그래서 SeekBar를의 OnSeekBarChangeListener()onStopTrackingTouch()onProgressChanged()에서 promptList.get(position).setSliderLevel(progress)를 이동하고, 또한 wrap_content에서의 ListView의 높이를 변경하여 문제를 해결하기 위해 관리했습니다 match_parent. 이 두 가지 모두 우울한 행동을 일으켰습니다.

seekListbar가 arrayList의 값으로 초기화 된 후 changeListener가 설정되어 있어도 어떤 이유로 런타임에 seekbar를 건드리지 않고도 onProgressChanged()가 호출되었습니다.

편집 : 0X0nosugar의 대답은이 동작

+0

serSliderLevel()이 수행하는 작업과 배치되는 위치를 알려주시겠습니까? –

관련 문제