2016-11-08 119 views
1

我在我的应用程序中有一个listView。对于listView中的每个元素,它都有一个Switch。以前我在listView Adapter的getView方法中为Switch实现了一个onClickListener。但是,我发现虽然它在用户单击交换机时工作,但当用户在交换机上滑动时,它不起作用。然后我尝试将onClickListener更改为onCheckedChangeListener。当用户在Switch上单击或滑动时,它可以工作,但是,当我滚动ListView以使元素消失时,我发现最初选中的Switch未被选中。Android:在ListView适配器中切换OnCheckedChangeListener

你能帮忙吗?下面是我的getView方法在ListView适配器代码:

@Override 
public View getView(final int position, View convertView, final ViewGroup parent) { 
    class viewHolder { 
     public TextView tvSceneName; 
     public Switch swSelectSwitch; 
    } 
    final viewHolder holder; 

    final View v = convertView; 

    // Use ViewHolder to avoid findViewById each time the user scroll 
    if (convertView == null) { 
     holder = new viewHolder(); 
     convertView = mInflater.inflate(R.layout.scene_list_element, parent, false); 
     holder.tvSceneName = (TextView) convertView.findViewById(R.id.tvSceneName); 
     holder.swSelectSwitch = (Switch) convertView.findViewById(R.id.swScene); 
     convertView.setTag(holder); 
    } else { 
     holder = (viewHolder) convertView.getTag(); 
    } 


    if(holder.swSelectSwitch != null) { 

     // Set the switch to correct on/off status 
     holder.swSelectSwitch.setChecked(mDataSource.get(position).get_isOn()); 

     // Set up On checked change listener for the switch 
     holder.swSelectSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
      @Override 
      public void onCheckedChanged(CompoundButton toggleButton, boolean isChecked) { 

       // Set the new status to arraylist 
       Switch sw = (Switch) v.findViewById(R.id.swScene); 
       MainActivity.sceneArrayList.get(position).set_isOn(sw.isChecked()); 

     }); 
    } 
} 

编辑: 在进一步的测试中,我发现有错误在我的新增onCheckChangedListener(因为我从复制的一些代码onClickListener)。另外我找到了一个解决方案,它是在我通过代码设置Switch之前将onCheckChangedListener设置为null。

if(holder.swSelectSwitch != null) { 

    // Set the switch to correct on/off status 
    holder.swSelectSwitch.setOnCheckedChangeListener(null); 
    holder.swSelectSwitch.setChecked(mDataSource.get(position).get_isOn()); 

    // Set up On checked change listener for the switch 
    holder.swSelectSwitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
     @Override 
     public void onCheckedChanged(CompoundButton toggleButton, boolean isChecked) { 

      // Set the new status to arraylist 
      mDataSource.get(position).set_isOn(isChecked); 

    }); 
} 
+1

您正在使用两个列表:

你应该mDataSource在发生变化时更新状态。他们有相同的参考?如果没有,你正在更新一个不同的列表,所以在你滚动之后清楚为什么你的复选框没有更新。其他的事情是你为什么不使用onCheckedChanged监听器的参数,而不是使用findviewbyId – Alex

+0

@Alex你是对的,我发现我应该使用isChecked参数。我使用findviewbyId,因为我只是从onClickedListner复制代码。 onClickedListener没有这个参数。列表是一样的。事实上,我不清楚如何使用listView,当它有很多组件和数据源是复杂的。 – eepty

回答

0

您应该删除行if(holder.swSelectSwitch != null) {: 滚动时,意见不被破坏,但回收的,所以当getView被滚动后调用,convertView不为空。当convertView不为空时,您将重新使用您已创建的持有者并放入视图标记中。

1

ViewHolder模式的要点在于View正在循环使用。

你从mDataSource获取的选中状态,但没有更新,所以当View得到回收的Switch返回其原始(未选中)状态。

@Override 
public void onCheckedChanged(CompoundButton toggleButton, boolean isChecked) { 

    // Set the new status to arraylist 
    MainActivity.sceneArrayList.get(position).set_isOn(isChecked); 

    // updating mDataSource 
    mDataSource.get(position).set_isOn(isChecked); 
}