2017-04-11 43 views
0

我使用RecyclerView它支持拖放面临setOnCheckedChangeListener位置值的问题。我的列表项有一行有两个TextView,CheckBox,ImageView用于拖动行。在RecyclerView的Android

我用的辅助类以下链接: https://github.com/iPaulPro/Android-ItemTouchHelper-Demo/tree/master/app/src/main/java/co/paulburke/android/itemtouchhelperdemo/helper

arrTaxStatus的价值观是正确的,当我拖行。 arrTaxStatus的

价值观是正确的,当我启用/禁用的复选框。

但我面临的问题时,我启用/禁用一些复选框,拖几行,然后再启用/禁用一些复选框。该位置在setOnCheckedChangeListener中受到干扰。即使我点击第一行,我得到一个不同的“位置”

请告诉我怎样才能获得点击复选框的正确位置。下面

代码:

public class RecyclerListFragment extends AppCompatActivity implements OnStartDragListener { 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.create_tax_group); 

    arrTaxStatus = new ArrayList<Boolean>(); 
    HashMap<String, Object> temp; 
    taxAccounts = new ArrayList<HashMap<String, Object>>(); 
    Cursor cursor = dh.getDetailsFromTaxGivenTaxCategory(); 
    if (cursor.moveToFirst()) { 
     do { 
      temp = new HashMap<String, Object>(); 
      temp.put("taxName", cursor.getString(cursor.getColumnIndex("scheme_name"))); 
      temp.put("taxPercent", numberFormat.format(cursor.getDouble(cursor.getColumnIndex("percentage")))); 
      taxAccounts.add(temp); 
      arrTaxStatus.add(false); 
     } while (cursor.moveToNext()); 
    } 
    cursor.close(); 

    RecyclerListAdapter adapter = new RecyclerListAdapter(this, taxAccounts); 

    RecyclerView recyclerView = (RecyclerView) findViewById(android.R.id.list); 
    recyclerView.setHasFixedSize(true); 
    recyclerView.setAdapter(adapter); 
    recyclerView.setLayoutManager(new LinearLayoutManager(this)); 

    ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(adapter); 
    mItemTouchHelper = new ItemTouchHelper(callback); 
    mItemTouchHelper.attachToRecyclerView(recyclerView); 
} 

@Override 
public void onStartDrag(RecyclerView.ViewHolder viewHolder) { 
    mItemTouchHelper.startDrag(viewHolder); 
} 

public class RecyclerListAdapter extends RecyclerView.Adapter<RecyclerListAdapter.ItemViewHolder> 
     implements ItemTouchHelperAdapter { 
    private final OnStartDragListener mDragStartListener; 

    public RecyclerListAdapter(OnStartDragListener dragStartListener, ArrayList<HashMap<String, Object>> taxAccounts) { 
     mDragStartListener = dragStartListener; 
    } 

    @Override 
    public ItemViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
     View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.create_tax_group_row, parent, false); 
     ItemViewHolder itemViewHolder = new ItemViewHolder(view); 
     return itemViewHolder; 
    } 

    @Override 
    public void onBindViewHolder(final ItemViewHolder holder, final int position) { 
     holder.taxName.setText(taxAccounts.get(position).get("taxName").toString()); 
     holder.taxPercent.setText(taxAccounts.get(position).get("taxPercent").toString()); 
     holder.handleView.setOnTouchListener(new View.OnTouchListener() { 
      @Override 
      public boolean onTouch(View v, MotionEvent event) { 
       if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) { 
        mDragStartListener.onStartDrag(holder); 
       } 
       return false; 
      } 
     }); 

     holder.taxStatus.setOnCheckedChangeListener(null); 
     holder.taxStatus.setChecked(arrTaxStatus.get(position)); 
     holder.taxStatus.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 
      public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
       Log.i("arrTaxStatus pos|checked", position + "|" + isChecked); 
       arrTaxStatus.set(position, isChecked); 
       Log.i("arrTaxStatus onCheckedChanged", arrTaxStatus.toString()); 
      } 
     }); 
    } 

    @Override 
    public void onItemDismiss(int position) { 
     taxAccounts.remove(position); 
     arrTaxStatus.remove(position); 
     notifyItemRemoved(position); 
    } 

    @Override 
    public boolean onItemMove(int fromPosition, int toPosition) { 
     Collections.swap(taxAccounts, fromPosition, toPosition); 
     Collections.swap(arrTaxStatus, fromPosition, toPosition); 
     Log.i("arrTaxStatus onItemMove", arrTaxStatus.toString()); 
     notifyItemMoved(fromPosition, toPosition); 
     return true; 
    } 

    @Override 
    public int getItemCount() { 
     return taxAccounts.size(); 
    } 

    /** 
    * Simple example of a view holder that implements {@link ItemTouchHelperViewHolder} and has a 
    * "handle" view that initiates a drag event when touched. 
    */ 
    public class ItemViewHolder extends RecyclerView.ViewHolder implements 
      ItemTouchHelperViewHolder { 

     public final TextView taxName, taxPercent; 
     public final CheckBox taxStatus; 
     public final ImageView handleView; 

     public ItemViewHolder(View itemView) { 
      super(itemView); 
      taxName = (TextView) itemView.findViewById(R.id.childname); 
      taxPercent = (TextView) itemView.findViewById(R.id.balance); 
      taxStatus = (CheckBox) itemView.findViewById(R.id.check_status); 
      handleView = (ImageView) itemView.findViewById(R.id.handle); 
     } 

     @Override 
     public void onItemSelected() { 
      itemView.setBackgroundColor(Color.LTGRAY); 
     } 

     @Override 
     public void onItemClear() { 
      itemView.setBackgroundColor(0); 
     } 
    } 
} 
} 

回答

0

你需要在你的数据模型e.g或器isChecked的IsEnabled创建一个变量。然后当你启用/禁用它们。只需更新您用来填充列表的数组。 然后onBindViewHoder检查变量值并启用/禁用复选框。

概念是行回收,一旦你向上/向下移动。所以复选框不会保留这些值。所以你需要保留数组中的值。然后填充它们。

0

而不是让从位置onbindviewholder设置标签,就可以布局持有排的位置,当你改变onchangelistner

0

可以使用notifyItemChanged(int position)方法从RecyclerView.Adapter class.从文档使用该标记值:

通知任何注册的观察者该位置的物品已更改。相当于调用notifyItemChanged(position, null);.

这是一个项目的变化事件,而不是一个结构变化事件。它表明任何对位置数据的反映都是过时的,应该更新。位置上的物品保留相同的身份。 因为你已经有了这个职位,所以应该适合你。

0

你需要保持一个标志为您的适配器如下:

private boolean onViewHolderBind; 

public ViewHolder(View itemView) { 
    super(itemView); 
    mCheckBox = (CheckBox) itemView.findViewById(R.id.checkboxId); 
    mCheckBox.setOnCheckChangeListener(this); 
} 

@Override 
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 
    if(!onViewHolderBind) { 
     // perform your process when checkbox changed 
     notifyDataSetChanged(); 
    } 
} 

... 

@Override 
public void onBindViewHolder(YourAdapter.ViewHolder viewHolder, int position) { 
    // process other views 
    // ... 

    onViewHolderBind = true; 
    viewHolder.mCheckBox.setChecked(trueOrFalse); 
    onViewHolderBind = false; 
} 
0

我想你是痛苦的问题是,通过适配器内部控制的项目不符合你的阵列同步,问题是那Collections.swap(…)不会做什么适配器执行图形。 A swap()将交换数组中两个项目的位置,但范围内的项目保持原位。但是,当用户从最后一个位置拖动一个项目到第一个位置时,范围内的所有项目位置都会变为

我开始使用此代码自己和通过用下面的代码(差异)替换swap()呼叫固定它:

 override fun onItemMove(fromPosition: Int, toPosition: Int): Boolean { 
-  Collections.swap(items, fromPosition, toPosition) 
+  val temp = items[fromPosition] 
+  items.removeAt(fromPosition) 
+  items.add(toPosition, temp) 
      notifyItemMoved(fromPosition, toPosition) 
      return true 
     } 

为了说明视觉上的缺陷,我添加了一个dump()呼叫是否显示的内容适配器每条拖相互作用后,然后创建的适配器具有七个元件,方便地放于字母顺序:

Adapter: did load 7 
Adapter: Dumping 7 items 
Adapter: …0 SharingItem(uri=content://FIRST, kind=Image) 
Adapter: …1 SharingItem(uri=content://B, kind=Image) 
Adapter: …2 SharingItem(uri=content://C, kind=Image) 
Adapter: …3 SharingItem(uri=content://D, kind=Audio) 
Adapter: …4 SharingItem(uri=content://E, kind=Audio) 
Adapter: …5 SharingItem(uri=content://F, kind=Video) 
Adapter: …6 SharingItem(uri=content://LAST, kind=Audio) 

在2×4网格显示这些项目,我拖着的最后一个项目到所述第一positio ñ。当我拖着手指,该项目将采取拖拽移动,这是由转储适配器接收每个互动强调在地方在收集的不同部分:

Adapter: Move from 6 to 4 
Adapter: Dumping 7 items 
Adapter: …0 SharingItem(uri=content://FIRST, kind=Image) 
Adapter: …1 SharingItem(uri=content://B, kind=Image) 
Adapter: …2 SharingItem(uri=content://C, kind=Image) 
Adapter: …3 SharingItem(uri=content://D, kind=Audio) 
Adapter: …4 SharingItem(uri=content://LAST, kind=Audio) 
Adapter: …5 SharingItem(uri=content://F, kind=Video) 
Adapter: …6 SharingItem(uri=content://E, kind=Audio) 
Adapter: Move from 4 to 2 
Adapter: Dumping 7 items 
Adapter: …0 SharingItem(uri=content://FIRST, kind=Image) 
Adapter: …1 SharingItem(uri=content://B, kind=Image) 
Adapter: …2 SharingItem(uri=content://LAST, kind=Audio) 
Adapter: …3 SharingItem(uri=content://D, kind=Audio) 
Adapter: …4 SharingItem(uri=content://C, kind=Image) 
Adapter: …5 SharingItem(uri=content://F, kind=Video) 
Adapter: …6 SharingItem(uri=content://E, kind=Audio) 
Adapter: Move from 2 to 0 
Adapter: Dumping 7 items 
Adapter: …0 SharingItem(uri=content://LAST, kind=Audio) 
Adapter: …1 SharingItem(uri=content://B, kind=Image) 
Adapter: …2 SharingItem(uri=content://FIRST, kind=Image) 
Adapter: …3 SharingItem(uri=content://D, kind=Audio) 
Adapter: …4 SharingItem(uri=content://C, kind=Image) 
Adapter: …5 SharingItem(uri=content://F, kind=Video) 
Adapter: …6 SharingItem(uri=content://E, kind=Audio) 

更换后在上面的实现中调用swap()时,日志显示交互期间内部的更好图片:

Adapter: did load 7 
Adapter: Dumping 7 items 
Adapter: …0 SharingItem(uri=content://FIRST, kind=Image) 
Adapter: …1 SharingItem(uri=content://B, kind=Image) 
Adapter: …2 SharingItem(uri=content://C, kind=Image) 
Adapter: …3 SharingItem(uri=content://D, kind=Audio) 
Adapter: …4 SharingItem(uri=content://E, kind=Audio) 
Adapter: …5 SharingItem(uri=content://F, kind=Video) 
Adapter: …6 SharingItem(uri=content://LAST, kind=Audio) 
Adapter: Move from 6 to 4 
Adapter: Dumping 7 items 
Adapter: …0 SharingItem(uri=content://FIRST, kind=Image) 
Adapter: …1 SharingItem(uri=content://B, kind=Image) 
Adapter: …2 SharingItem(uri=content://C, kind=Image) 
Adapter: …3 SharingItem(uri=content://D, kind=Audio) 
Adapter: …4 SharingItem(uri=content://LAST, kind=Audio) 
Adapter: …5 SharingItem(uri=content://E, kind=Audio) 
Adapter: …6 SharingItem(uri=content://F, kind=Video) 
Adapter: Move from 4 to 2 
Adapter: Dumping 7 items 
Adapter: …0 SharingItem(uri=content://FIRST, kind=Image) 
Adapter: …1 SharingItem(uri=content://B, kind=Image) 
Adapter: …2 SharingItem(uri=content://LAST, kind=Audio) 
Adapter: …3 SharingItem(uri=content://C, kind=Image) 
Adapter: …4 SharingItem(uri=content://D, kind=Audio) 
Adapter: …5 SharingItem(uri=content://E, kind=Audio) 
Adapter: …6 SharingItem(uri=content://F, kind=Video) 
Adapter: Move from 2 to 0 
Adapter: Dumping 7 items 
Adapter: …0 SharingItem(uri=content://LAST, kind=Audio) 
Adapter: …1 SharingItem(uri=content://FIRST, kind=Image) 
Adapter: …2 SharingItem(uri=content://B, kind=Image) 
Adapter: …3 SharingItem(uri=content://C, kind=Image) 
Adapter: …4 SharingItem(uri=content://D, kind=Audio) 
Adapter: …5 SharingItem(uri=content://E, kind=Audio) 
Adapter: …6 SharingItem(uri=content://F, kind=Video)