更多关于RecyclerView

这一次主要是关于ItemTouchHelper实现拖拽、滑动的效果。

ItemTouchHelper

This is a utility class to add swipe to dismiss and drag & drop support to RecyclerView.

It works with a RecyclerView and a Callback class, which configures what type of interactions are enabled and also receives events when user performs these actions.

——Android Developer

上面那句话是Google官方的介绍。

ItemTouchHelper是一个工具类,协助RecyclerView来实现滑动删除、拖拽和摆放。

ItemTouchHelper需要RecyclerView和Callback类。Callback类定义了被允许的交互类型,在用户进行这些交互操作时接受交互事件。

翻译过来差不多就是这样。

ItemTouchHelper的实例化需要ItemTouchHelper.Callback作为参数:

mItemTouchHelper = new ItemTouchHelper(ItemTouchHelper.Callback callback);

ItemTouchHelper.Callback

ItemTouchHelper.Callback是一个静态抽象类,一般重写的方法有下列几个:

getMovementFlags

该方法规定了item拖拽和滑动的方向。

public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
    int dragFlags = 0, swipeFlags = 0;
    if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {
        dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
        swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
    } else if (recyclerView.getLayoutManager() instanceof StaggeredGridLayoutManager) {
        dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN | ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT;
        swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
    }
    return makeMovementFlags(dragFlags, swipeFlags);
}

dragFlagsswipeFlags分别代表拖拽的方向和滑动的方向。

在该方法中,根据LayoutManager的类型来设置dragFlagsswipeFlags。当LayoutManagerLinearLayoutManager时,设置dragFlags为上下滑动和swipeFlags为左右滑动。

方法返回类型为int,可以通过makeMovementFlag并传入设置的两个参数来生成返回值。

onMove

该方法在item被移动时被调用,通常作数据的交换处理。

public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) {
	int from = viewHolder.getAdapterPosition();
	int to = target.getAdapterPosition();
	Collections.swap(adapter.data, from, to);
	adapter.notifyItemMoved(from, to);
	return true;
}

在本例中,通过viewHoldergetAdapterPosition方法得到被移动item和目前位置的item各自在数据源中的索引,利用索引交换数据源中对应的值,并使用adapter.notifyItemMoved()来更新视图。

返回值为true说明确认item被移动到目标位置。

onSwiped

该方法在item被滑动完成后调用,一般滑动指的是左右滑动。可以在这个方法里面作数据的删除操作。

public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
	int apos = viewHolder.getAdapterPosition();
	int lpos = viewHolder.getLayoutPosition();
	adapter.notifyItemRemoved(lpos);
	adapter.data.remove(apos);
}

onSelectedChanged

该方法在item的状态开始改变时调用。可以在方法里判断actionState的值来作出相应操作,如actionState判定为拖拽时改变item的背景等。

public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
	super.onSelectedChanged(viewHolder, actionState);
	if (actionState==ItemTouchHelper.ACTION_STATE_DRAG) {
			viewHolder.itemView.setBackground(ContextCompat.getDrawable(DragAnimActivity.this, R.drawable.radius_highlight));
	}
}

onChildDraw

该方法在item的状态正在改变时调用,也可以通过actionState作出相应操作,比如在方法里作一些动画效果。此处在actionState判定为滑动时,使item的透明度随着滑动距离而变化。

public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
	super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
	if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
			viewHolder.itemView.setAlpha(1 - Math.abs(dX) / 1080);
	}
}

clearView

该方法在item的状态改变结束时调用,一般用来清除onSelectedChanged中设置的样式(重置样式)。同样可以通过判定actionState的数值来作出不同操作。

public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
	super.clearView(recyclerView, viewHolder);
	viewHolder.itemView.setBackground(ContextCompat.getDrawable(DragAnimActivity.this, R.drawable.radius_white));
}

效果

总结

不想说太多,RecyclerView就是好用。