我有一个RecyclerView,它添加了应该拖放的项目,但是,当添加项目时,我尝试将其交换,并抛出IndexOutOfBoundException
RecyclerView观察到一个ViewModel,当添加了某些块时,该ViewModel会刷新信息,我已经使用LiveData来实现它。
当列表中有一定数量的项目时,我的解决方案效果很好,当我尝试向RecyclerView中添加某些内容时,就会出现问题。
我已经用包含以下内容的类扩展了ItemTouchHelper.SimpleCallBack RecyclerView的适配器,但是当添加项目时,大小却不会改变(我尝试过手动设置,但无法使用)。
我试图通过调用来分离TouchHelper
touchHelper?.attachToRecyclerView(null)
,然后使用新的回调将其重新附加,但也无法正常工作。
这就是活动
class CreateWorkflowActivity: AppCompatActivity(), View.OnClickListener {
var touchHelper:ItemTouchHelper?= null
private lateinit var callback:ItemMoveCallback
private lateinit var rec_view: RecyclerView
companion object {
private lateinit var viewModel : WorkflowViewModel
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_create_workflow)
val factory= InjectorUtils.provideWorkflowViewModelFactory("")
viewModel = ViewModelProviders.of(this,factory).get(WorkflowViewModel::class.java)
rec_view= findViewById(R.id.recyclerView_addedBlocksOnCreation)
rec_view.layoutManager= LinearLayoutManager(this)
val observer = Observer<ArrayList<String>>{
val adapter = BlockViewAdapter(it!!, this@CreateWorkflowActivity)
callback= ItemMoveCallback(adapter,this@CreateWorkflowActivity,ItemTouchHelper.UP.or(ItemTouchHelper.DOWN),0)
touchHelper= ItemTouchHelper(callback)
touchHelper?.attachToRecyclerView(rec_view)
runOnUiThread{
rec_view.adapter= adapter
}
}
viewModel.getLiveBlockNames().observe(this,observer)
}
//this gets called when the user has decided the parameters for the block
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if(requestCode == 1) {
if(resultCode==Activity.RESULT_OK) {
//all block additions
}
}
}
}
}
这扩展了ItemTouchHelper.SimpleCallBack
class ItemMoveCallback(adapter: BlockViewAdapter, context: Context, dragDirs: Int, swipeDirs: Int) : ItemTouchHelper.SimpleCallback(dragDirs, swipeDirs)
{
var mAdapter = adapter
override fun onSwiped(p0: RecyclerView.ViewHolder, p1: Int) {
return
}
override fun onMove(p0: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
mAdapter.swapItems(viewHolder.adapterPosition, target.adapterPosition)
return true
}
fun setAdapter(adapter: BlockViewAdapter){
mAdapter=adapter
}
}
这是适配器(我已经省略了BlockViewHolder,因为它很标准)
class BlockViewAdapter(val dataset: ArrayList<String>,val context: Context): RecyclerView.Adapter<BlockViewHolder>(){
@SuppressLint("ClickableViewAccessibility")
override fun onBindViewHolder(holder: BlockViewHolder, position: Int) {
holder.tView?.text = dataset[position]
}
override fun getItemCount(): Int {
return dataset.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BlockViewHolder {
return BlockViewHolder(
LayoutInflater.from(context).inflate(
R.layout.block_item,
parent,
false
)
)
}
fun swapItems(fromPosition: Int, toPosition: Int) {
if (fromPosition < toPosition) {
for (i in fromPosition..toPosition - 1) {
dataset.set(i, dataset.set(i+1, dataset.get(i)))
}
} else {
for (i in fromPosition..toPosition + 1) {
dataset.set(i, dataset.set(i-1, dataset.get(i)))
}
}
notifyItemMoved(fromPosition, toPosition)
}
}
答案 0 :(得分:0)
@Ludovico Brocca您正在遇到IndexOutOfBoundException
,因为在向适配器添加新项后没有调用notifyDataSetChanged()
。
因此,仅使用上下文初始化适配器,然后将各项作为设置器。 以下示例可供参考:
class BlockViewAdapter(val context: Context) : RecyclerView.Adapter<BlockViewHolder>() {
var dataset: List<String> = emptyList()
set(value) {
// might have to do this on main thread
field = value
notifyDataSetChanged()
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): BlockViewHolder {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun onBindViewHolder(holder: BlockViewHolder, position: Int) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override fun getItemCount(): Int {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}