2016-11-08 7 views
1

私は自分のアプリケーションにlistViewを持っています。 listViewの各要素には、スイッチがあります。以前は、ListViewアダプタのgetViewメソッドの中にスイッチ用のonClickListenerを実装しました。しかし、ユーザーがスイッチをクリックしても機能しますが、スイッチをスライドさせると機能しません。次に、onClickListenerをonCheckedChangeListenerに変更しようとします。ユーザーがスイッチをクリックまたはスライドすると動作しますが、リストビューをスクロールして要素が消えると、最初にチェックされたスイッチがチェックされなくなります。Android:ListViewアダプタのOnCheckedChangeListenerを切り替えます。

お手伝いできますか?以下は、リストビューアダプタでGetViewメソッドのために私のコードです:

@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()); 

     }); 
    } 
} 

EDIT: さらにテストでは、私はからいくつかのコードをコピーしたので、バグが私の新たに追加したonCheckChangedListener(中に存在しましたonClickListener)を呼び出します。また、解決策を見つけました。コードでスイッチを設定する前に、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

次の2つのリストを使用しています。彼らには同じ参照がありますか?そうでない場合は、スクロールした後に別のリストを更新すると、チェックボックスが更新されない理由がわかります。他には、findviewbyIdを使用する代わりに、onCheckedChangedリスナーのパラメータを使用しない理由があります。 – Alex

+0

@Alexそうです。isCheckedパラメータを使用する必要があります。私はonClickedListnerからコードをコピーするだけなので、findviewbyIdを使用します。 onClickedListenerにはこのパラメータはありません。リストも同じです。実際、多くのコンポーネントがあり、データソースが複雑なときに、listViewの使い方についてはあまり明確ではありません。 – eepty

答えて

0

あなたがラインif(holder.swSelectSwitch != null) {削除する必要があります:あなたがスクロールすると、ビューが破壊されたが、リサイクルされていない を、そうgetViewをスクロールした後に呼び出されたとき、convertViewはNULLではありません。 convertViewがnullでない場合は、すでに作成したホルダーを再利用して、ビュー・タグに入れます。

1

ViewHolderパターンのポイントは、Viewがリサイクルされているということです。

チェック状態をmDataSourceからフェッチしていますが、更新していないため、がリサイクルされると、Switchは元の(チェックされていない)状態に戻ります。

変更が発生したときにあなたがmDataSourceに状態を更新する必要があります

@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); 
} 
関連する問題