话不多说,直接上图,看看是不是你的菜~
ItemTouchHelper
了解RecyclerView的同学都知道,item的操作都是通过ItemTouchHelper来处理的。
ItemTouchHelper
用法很简单,初始化,然后绑定RecyclerView
即可
ItemTouchHelper mItemTouchHelper = new ItemTouchHelper(callback);
mItemTouchHelper.attachToRecyclerView(like_me_list);
注意到ItemTouchHelper
初始化时的参数了吗?
其实这个callback就是ItemTouchHelper.Callback
,ItemTouchHelper.Callback
是对item操作的回调类,比如item的move swipe等。
要想定制化我们的左右滑,最重要的就是重写ItemTouchHelper.Callback
ItemTouchHelper.Callback
实现如上GIF的效果
- 点击时,所点击的view要提到顶部(不然会被其他的item遮盖)
- 根据滑动的轨迹,让item按照需要的轨迹移动
- 移动的参数,移动后的处理
点击时,所点击的view要提到顶部
参考了源码,长按拖动时,item就是提到顶部的。
public static void takeViewTopInRec(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, boolean isCurrentlyActive) {
if (Build.VERSION.SDK_INT >= 21 && isCurrentlyActive) {
Object originalElevation = viewHolder.itemView.getTag(android.support.v7.recyclerview.R.id.item_touch_helper_previous_elevation);
if (originalElevation == null) {
originalElevation = ViewCompat.getElevation(viewHolder.itemView);
float newElevation = 1.0F + findMaxElevation(recyclerView, viewHolder.itemView);
ViewCompat.setElevation(viewHolder.itemView, newElevation);
viewHolder.itemView.setTag(android.support.v7.recyclerview.R.id.item_touch_helper_previous_elevation, originalElevation);
}
}
}
private static float findMaxElevation(RecyclerView recyclerView, View itemView) {
int childCount = recyclerView.getChildCount();
float max = 0.0F;
for (int i = 0; i < childCount; ++i) {
View child = recyclerView.getChildAt(i);
if (child != itemView) {
float elevation = ViewCompat.getElevation(child);
if (elevation > max) {
max = elevation;
}
}
}
return max;
}
根据滑动的轨迹,让item按照需要的轨迹移动
@Override
public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
//为了把view提到顶部
takeViewTopInRec(recyclerView, viewHolder, isCurrentlyActive);
final int width = viewHolder.itemView.getWidth();
final int height = viewHolder.itemView.getHeight();
// Fade out the view as it is swiped out of the parent's bounds
final float r = Math.abs(dX) / (float) width;
final float alpha = ALPHA_FULL - r;
viewHolder.itemView.setTranslationX(dX * 1.1f);
if (r < 0.3) {
viewHolder.itemView.setScaleX(1 + r * 0.2f);
viewHolder.itemView.setScaleY(1 + r * 0.2f);
}
viewHolder.itemView.setTranslationY(r * height * 0.2f);
if (dX >= 0) {
swipeAction = MatchPairConstant.LIKE_ACTION;
viewHolder.itemView.setRotation(10 * r);
((RecyclerGridSlipAdapter.ItemViewHolder) viewHolder).like.setAlpha(r * 4f > 1 ? 1f : r * 4f);
((RecyclerGridSlipAdapter.ItemViewHolder) viewHolder).dislike.setAlpha(0f);
} else {
swipeAction = MatchPairConstant.DIS_LIKE_ACTION;
viewHolder.itemView.setRotation(-10 * r);
((RecyclerGridSlipAdapter.ItemViewHolder) viewHolder).dislike.setAlpha(r * 4f > 1 ? 1f : r * 4f);
((RecyclerGridSlipAdapter.ItemViewHolder) viewHolder).like.setAlpha(0f);
}
/*if (r > 0.5) {
viewHolder.itemView.setAlpha(alpha * 2f);
}*/
} else {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
}
移动的参数,移动后的处理
//滑动到删除的速度
@Override
public float getSwipeEscapeVelocity(float defaultValue) {
return super.getSwipeEscapeVelocity(defaultValue);
}
@Override
public long getAnimationDuration(@NonNull RecyclerView recyclerView, int animationType, float animateDx, float animateDy) {
return 400;
//return super.getAnimationDuration(recyclerView, animationType, animateDx, animateDy);
}
//滑动到删除的距离
@Override
public float getSwipeThreshold(@NonNull RecyclerView.ViewHolder viewHolder) {
//return super.getSwipeThreshold(viewHolder);
return 0.30f;
}
@Override
public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
viewHolder.itemView.setAlpha(ALPHA_FULL);
viewHolder.itemView.setRotation(0);
viewHolder.itemView.setTranslationX(0);
viewHolder.itemView.setTranslationY(0);
viewHolder.itemView.setScaleX(1);
viewHolder.itemView.setScaleY(1);
((RecyclerGridSlipAdapter.ItemViewHolder) viewHolder).like.setAlpha(0f);
((RecyclerGridSlipAdapter.ItemViewHolder) viewHolder).dislike.setAlpha(0f);
// Tell the view holder it's time to restore the idle state
ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
itemViewHolder.onItemClear();
}
//支持滑动的模式(左右)
@Override
public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
// Set movement flags based on the layout manager
final int dragFlags = 0;
final int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
return makeMovementFlags(dragFlags, swipeFlags);
}
上面的代码就是核心了,但是还不足以让程序跑起来。我们要把某些行为(选中了item/移除了item/item移除后重置等)通知业务层
ItemTouchHelperAdapter
public interface ItemTouchHelperAdapter {
/**
* Called when an item has been dragged far enough to trigger a move. This is called every time
* an item is shifted, and <strong>not</strong> at the end of a "drop" event.<br/>
* <br/>
* Implementations should call {@link RecyclerView.Adapter#notifyItemMoved(int, int)} after
* adjusting the underlying data to reflect this move.
*
* @param fromPosition The start position of the moved item.
* @param toPosition Then resolved position of the moved item.
* @return True if the item was moved to the new adapter position.
* @see RecyclerView#getAdapterPositionFor(RecyclerView.ViewHolder)
* @see RecyclerView.ViewHolder#getAdapterPosition()
*/
boolean onItemMove(int fromPosition, int toPosition);
/**
* Called when an item has been dismissed by a swipe.<br/>
* <br/>
* Implementations should call {@link RecyclerView.Adapter#notifyItemRemoved(int)} after
* adjusting the underlying data to reflect this removal.
*
* @param position The position of the item dismissed.
* @see RecyclerView#getAdapterPositionFor(RecyclerView.ViewHolder)
* @see RecyclerView.ViewHolder#getAdapterPosition()
*/
void onItemDismiss(String action, int position);
void onItemReset(@NonNull RecyclerView.ViewHolder viewHolder, int position);
}
public interface ItemTouchHelperViewHolder {
/**
* Called when the {@link ItemTouchHelper} first registers an item as being moved or swiped.
* Implementations should update the item view to indicate it's active state.
*/
void onItemSelected();
/**
* Called when the {@link ItemTouchHelper} has completed the move or swipe, and the active item
* state should be cleared.
*/
void onItemClear();
}
实现了ItemTouchHelperAdapter的自定义apapter ,重写这些方法即可
@Override
public void onItemDismiss(String action, int position) {
final LikeMeDetailEntity likeMeDetailEntity = mItems.get(position);
mItems.remove(position);
notifyItemRemoved(position);
if (mExecuteListener != null) {
mExecuteListener.onLikeActionCallback(position, likeMeDetailEntity, action);
}
}
@Override
public boolean onItemMove(int fromPosition, int toPosition) {
Collections.swap(mItems, fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
return true;
}
@Override
public void onItemReset(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
//notifyDataSetChanged();
ToastUtils.showToast(GlobalContext.getString(R.string.no_like_me_like_time));
notifyItemChanged(position);
}
当然,还要支持点击右滑
private void swipeRight(final LikeMeDetailEntity detailEntity, ItemViewHolder holder, final int position) {
clearAnim();
final int widthPixels = GlobalContext.getDisplayMetrics().widthPixels;
if (mExecuteListener != null) {
mExecuteListener.onLikeAnimExecuteListener(LikeExecuteListener.START);
}
LikeMeItemTouchHelperCallback.takeViewTopInRec(recyclerView, holder, true);
final View itemView = holder.itemView;
final View like = holder.like;
ValueAnimator rotation = ObjectAnimator.ofPropertyValuesHolder(
itemView, PropertyValuesHolder.ofFloat("rotation", 30f));
rotation.setDuration(300);
float trans = itemView.getWidth() + widthPixels;
ValueAnimator translateX = ObjectAnimator.ofPropertyValuesHolder(
itemView, PropertyValuesHolder.ofFloat("translationX", 0f, trans));
ValueAnimator translateY = ObjectAnimator.ofPropertyValuesHolder(
itemView, PropertyValuesHolder.ofFloat("translationY", 0f, DisplayUtil.dip2px(GlobalContext.getAppContext(), 265 * 0.2f)));
translateX.setDuration(500);
translateY.setDuration(500);
cardAnimationSet = new AnimatorSet();
cardAnimationSet.setInterpolator(new AccelerateInterpolator());
cardAnimationSet.playTogether(rotation, translateX, translateY);
cardAnimationSet.start();
ObjectAnimator overlayAnimator = ObjectAnimator.ofFloat(like, "alpha", 0f, 1f);
overlayAnimator.setDuration(300);
likeActionAnimationSet = new AnimatorSet();
likeActionAnimationSet.playTogether(overlayAnimator);
likeActionAnimationSet.start();
cardAnimationSet.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
if (position < mItems.size()) {
mItems.remove(position);
notifyItemRemoved(position);
if (mExecuteListener != null) {
mExecuteListener.onLikeAnimExecuteListener(LikeExecuteListener.END);
mExecuteListener.onLikeActionCallback(position, detailEntity, MatchPairConstant.LIKE_ACTION);
}
} else {
notifyDataSetChanged();
}
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
schedule = AndroidSchedulers.mainThread().createWorker()
.schedule(new Action0() {
@Override
public void call() {
itemView.setRotation(0);
itemView.setTranslationX(0);
itemView.setTranslationY(0);
like.setAlpha(0f);
}
}, 800, TimeUnit.MILLISECONDS);
}
完整代码
完整代码掺杂了很多业务逻辑,但不影响同学们理解。看大题的用法即可
LikeMeActivity
public class LikeMeActivity extends BaseActivity implements View.OnClickListener {
private TextView like_me_num;
private RecyclerView like_me_list;
private View empty_view;
private CompositeSubscription mSubscription = new CompositeSubscription();
private RecyclerGridSlipAdapter adapter;
private List<LikeMeDetailEntity> likeMes;
private SwipeRefreshLayout swipe_refresh;
private LikeMeItemTouchHelperCallback callback;
private LikeMeModel mLikeMeModel = new LikeMeModel();
//是不是最后一页
private boolean is_last_page = false;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.like_me_layout);
like_me_num = findViewById(R.id.like_me_num);
like_me_list = findViewById(R.id.like_me_list);
swipe_refresh = findViewById(R.id.swipe_refresh);
empty_view = findViewById(R.id.empty_view);
findViewById(R.id.like_me_title).setOnClickListener(this);
findViewById(R.id.page_back).setOnClickListener(this);
adapter = new RecyclerGridSlipAdapter();
like_me_list.setHasFixedSize(true);
like_me_list.setAdapter(adapter);
like_me_list.setLayoutManager(new GridLayoutManager(this, 2));
callback = new LikeMeItemTouchHelperCallback(adapter);
ItemTouchHelper mItemTouchHelper = new ItemTouchHelper(callback);
mItemTouchHelper.attachToRecyclerView(like_me_list);
adapter.setExecuteListener(new RecyclerGridSlipAdapter.LikeExecuteListener() {
@Override
public void onLikeAnimExecuteListener(int status) {
switch (status) {
case RecyclerGridSlipAdapter.LikeExecuteListener.START:
callback.setCanSwipe(false);
break;
case RecyclerGridSlipAdapter.LikeExecuteListener.END:
callback.setCanSwipe(true);
break;
}
}
@Override
public void onLikeActionCallback(int position, LikeMeDetailEntity likeDetail, String action) {
likeAction(position, likeDetail, action);
}
});
loadData(0);
like_me_list.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
if (recyclerView.getLayoutManager() == null) {
return;
}
//当前RecyclerView显示出来的最后一个的item的position
int lastPosition = -1;
//当前状态为停止滑动状态SCROLL_STATE_IDLE时
if (newState == RecyclerView.SCROLL_STATE_IDLE) {
RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
if (layoutManager instanceof GridLayoutManager) {
//通过LayoutManager找到当前显示的最后的item的position
lastPosition = ((GridLayoutManager) layoutManager).findLastVisibleItemPosition();
}
//时判断界面显示的最后item的position是否等于itemCount总数-1也就是最后一个item的position
//如果相等则说明已经滑动到最后了
if (lastPosition == recyclerView.getLayoutManager().getItemCount() - 1) {
loadData(likeMes != null && !likeMes.isEmpty() ? likeMes.get(likeMes.size() - 1).beliked_timestamp : 0);
}
}
}
});
swipe_refresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
@Override
public void onRefresh() {
loadData(0);
final Subscription schedule = AndroidSchedulers.mainThread()
.createWorker()
.schedule(new Action0() {
@Override
public void call() {
swipe_refresh.setRefreshing(false);
}
}, 300, TimeUnit.MILLISECONDS);
mSubscription.add(schedule);
}
});
}
private void loadData(final long last_timestamp) {
if (is_last_page && last_timestamp != 0) {
return;
}
final Subscription subscribe = MatchPairNetManager.getLikeMeList(last_timestamp)
.doOnNext(new Action1<RspQueenDefault<LikeMeResult>>() {
@Override
public void call(RspQueenDefault<LikeMeResult> rsp) {
swipe_refresh.setRefreshing(false);
if (rsp.isSuccess() && rsp.getResultEntity() != null && rsp.getResultEntity().data != null) {
if (last_timestamp == 0) {
if (rsp.getResultEntity().data.items == null || rsp.getResultEntity().data.items.isEmpty()) {
empty_view.setVisibility(View.VISIBLE);
} else {
empty_view.setVisibility(View.GONE);
}
} else {
empty_view.setVisibility(View.GONE);
}
callback.setLike_num(rsp.getResultEntity().data.left_like_count);
adapter.setLike_num(rsp.getResultEntity().data.left_like_count);
final LikeMeInfoEntity data = rsp.getResultEntity().data;
like_me_num.setText(String.valueOf(data.beliked_num));
if (last_timestamp != 0) {
mergeListView(data.items);
} else {
likeMes = rsp.getResultEntity().data.items;
}
adapter.refreshAllDate(likeMes);
is_last_page = rsp.getResultEntity().data.is_last_page == 1;
} else {
if (last_timestamp == 0) {
empty_view.setVisibility(View.VISIBLE);
}
}
}
})
.subscribe(new DefaultSubscriber<>("refreshData"));
mSubscription.add(subscribe);
}
private void likeAction(final int position, final LikeMeDetailEntity likeDetail, final String action) {
final Subscription subscribe = mLikeMeModel.beLikeAction(likeDetail.info.uid, action)
.doOnNext(new Action1<RspQueenDefault<LikeMeActionResult>>() {
@Override
public void call(RspQueenDefault<LikeMeActionResult> rsp) {
if (!rsp.isSuccess) {
ToastUtils.showToast(rsp.getErrorMessage());
//adapter.insertDate(position, likeDetail);
}
if (rsp.isSuccess && rsp.getResultEntity() != null && rsp.getResultEntity().data != null) {
callback.setLike_num(rsp.getResultEntity().data.left_like_count);
adapter.setLike_num(rsp.getResultEntity().data.left_like_count);
if (TextUtils.equals(action, MatchPairConstant.LIKE_ACTION)) {
final AppInNotifyManager notifyManager = new AppInNotifyManager();
notifyManager.setActivity(LikeMeActivity.this);
notifyManager.showInnerNotifyView(new AppInnerEntity(likeDetail.info), AppInnerNotifyView.NOTIFY_LIKE_ME, new AppInnerNotifyView.InnerNotifyClickListener() {
@Override
public void onInnerNotifyClickListener() {
ChatUiManager.startMessagePage(LikeMeActivity.this, likeDetail.info.uid, QueenChatConstant.FROM_NOTIFY);
}
});
}
removeItem(likeDetail.info.uid);
if (likeMes == null || likeMes.isEmpty()) {
empty_view.setVisibility(View.VISIBLE);
} else {
empty_view.setVisibility(View.GONE);
}
}
}
})
.subscribe(new DefaultSubscriber<>("likeAction"));
mSubscription.add(subscribe);
}
@Override
protected void onResume() {
super.onResume();
if (!EventBus.getDefault().isRegistered(this)) {
EventBus.getDefault().register(this);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mSubscription.clear();
if (adapter != null) {
adapter.release();
}
EventBus.getDefault().unregister(this);
}
@Subscribe
public void onEventMainThread(BeLikeLikeSuccessEvent event) {
//收到喜欢的通知,需要将此人移除
if (event != null) {
final int uid = event.uid;
removeItem(uid);
if (likeMes == null || likeMes.isEmpty()) {
empty_view.setVisibility(View.VISIBLE);
} else {
empty_view.setVisibility(View.GONE);
}
}
}
private void removeItem(int uid) {
for (int i = 0; likeMes != null && i < likeMes.size(); i++) {
if (likeMes.get(i) != null &&
likeMes.get(i).info != null &&
likeMes.get(i).info.uid == uid) {
likeMes.remove(i);
if (adapter != null) {
adapter.refreshAllDate(likeMes);
}
break;
}
}
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.page_back:
finish();
break;
}
}
private static final String TAG = "LikeMeActivity";
private void mergeListView(List<LikeMeDetailEntity> likeMesNow) {
if (likeMes == null || likeMes.isEmpty()) {
likeMes = likeMesNow;
return;
}
if (likeMesNow != null && !likeMesNow.isEmpty()) {
Iterator iterator = likeMesNow.iterator();
while (iterator.hasNext()) {
final LikeMeDetailEntity next = (LikeMeDetailEntity) iterator.next();
if (likeMes.contains(next)) {
iterator.remove();
}
}
likeMes.addAll(likeMesNow);
}
}
}
LikeMeItemTouchHelperCallback
/**
* 谁喜欢我订制
*/
public class LikeMeItemTouchHelperCallback extends ItemTouchHelper.Callback {
private static final String TAG = "SlipItemTouchHelperCall";
private String swipeAction = "";
public static final float ALPHA_FULL = 1.0f;
private final ItemTouchHelperAdapter mAdapter;
private boolean isCanSwipe = true;
private int like_num;
public void setLike_num(int like_num) {
this.like_num = like_num;
}
public LikeMeItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
mAdapter = adapter;
}
public void setCanSwipe(boolean canSwipe) {
isCanSwipe = canSwipe;
}
@Override
public boolean isLongPressDragEnabled() {
return false;
}
@Override
public boolean isItemViewSwipeEnabled() {
return isCanSwipe;
}
@Override
public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
// Set movement flags based on the layout manager
final int dragFlags = 0;
final int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
return makeMovementFlags(dragFlags, swipeFlags);
}
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder source, @NonNull RecyclerView.ViewHolder target) {
if (source.getItemViewType() != target.getItemViewType()) {
return false;
}
// Notify the adapter of the move
mAdapter.onItemMove(source.getAdapterPosition(), target.getAdapterPosition());
return true;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
// Notify the adapter of the dismissal
if (like_num <= 0 && TextUtils.equals(swipeAction, MatchPairConstant.LIKE_ACTION)) {
//如果剩余喜欢次数小于零,并且是喜欢,则反馈
mAdapter.onItemReset(viewHolder, viewHolder.getAdapterPosition());
} else {
mAdapter.onItemDismiss(swipeAction, viewHolder.getAdapterPosition());
}
swipeAction = "";
}
//滑动到删除的速度
@Override
public float getSwipeEscapeVelocity(float defaultValue) {
return super.getSwipeEscapeVelocity(defaultValue);
}
@Override
public long getAnimationDuration(@NonNull RecyclerView recyclerView, int animationType, float animateDx, float animateDy) {
return 400;
//return super.getAnimationDuration(recyclerView, animationType, animateDx, animateDy);
}
//滑动到删除的距离
@Override
public float getSwipeThreshold(@NonNull RecyclerView.ViewHolder viewHolder) {
//return super.getSwipeThreshold(viewHolder);
return 0.30f;
}
@Override
public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) {
//为了把view提到顶部
takeViewTopInRec(recyclerView, viewHolder, isCurrentlyActive);
final int width = viewHolder.itemView.getWidth();
final int height = viewHolder.itemView.getHeight();
// Fade out the view as it is swiped out of the parent's bounds
final float r = Math.abs(dX) / (float) width;
final float alpha = ALPHA_FULL - r;
viewHolder.itemView.setTranslationX(dX * 1.1f);
if (r < 0.3) {
viewHolder.itemView.setScaleX(1 + r * 0.2f);
viewHolder.itemView.setScaleY(1 + r * 0.2f);
}
viewHolder.itemView.setTranslationY(r * height * 0.2f);
if (dX >= 0) {
swipeAction = MatchPairConstant.LIKE_ACTION;
viewHolder.itemView.setRotation(10 * r);
((RecyclerGridSlipAdapter.ItemViewHolder) viewHolder).like.setAlpha(r * 4f > 1 ? 1f : r * 4f);
((RecyclerGridSlipAdapter.ItemViewHolder) viewHolder).dislike.setAlpha(0f);
} else {
swipeAction = MatchPairConstant.DIS_LIKE_ACTION;
viewHolder.itemView.setRotation(-10 * r);
((RecyclerGridSlipAdapter.ItemViewHolder) viewHolder).dislike.setAlpha(r * 4f > 1 ? 1f : r * 4f);
((RecyclerGridSlipAdapter.ItemViewHolder) viewHolder).like.setAlpha(0f);
}
/*if (r > 0.5) {
viewHolder.itemView.setAlpha(alpha * 2f);
}*/
} else {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
}
}
@Override
public void onSelectedChanged(RecyclerView.ViewHolder viewHolder, int actionState) {
// We only want the active item to change
if (actionState != ItemTouchHelper.ACTION_STATE_IDLE) {
if (viewHolder instanceof ItemTouchHelperViewHolder) {
// Let the view holder know that this item is being moved or dragged
ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
itemViewHolder.onItemSelected();
}
}
super.onSelectedChanged(viewHolder, actionState);
}
@Override
public void clearView(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) {
super.clearView(recyclerView, viewHolder);
viewHolder.itemView.setAlpha(ALPHA_FULL);
viewHolder.itemView.setRotation(0);
viewHolder.itemView.setTranslationX(0);
viewHolder.itemView.setTranslationY(0);
viewHolder.itemView.setScaleX(1);
viewHolder.itemView.setScaleY(1);
((RecyclerGridSlipAdapter.ItemViewHolder) viewHolder).like.setAlpha(0f);
((RecyclerGridSlipAdapter.ItemViewHolder) viewHolder).dislike.setAlpha(0f);
// Tell the view holder it's time to restore the idle state
ItemTouchHelperViewHolder itemViewHolder = (ItemTouchHelperViewHolder) viewHolder;
itemViewHolder.onItemClear();
}
public static void takeViewTopInRec(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, boolean isCurrentlyActive) {
if (Build.VERSION.SDK_INT >= 21 && isCurrentlyActive) {
Object originalElevation = viewHolder.itemView.getTag(android.support.v7.recyclerview.R.id.item_touch_helper_previous_elevation);
if (originalElevation == null) {
originalElevation = ViewCompat.getElevation(viewHolder.itemView);
float newElevation = 1.0F + findMaxElevation(recyclerView, viewHolder.itemView);
ViewCompat.setElevation(viewHolder.itemView, newElevation);
viewHolder.itemView.setTag(android.support.v7.recyclerview.R.id.item_touch_helper_previous_elevation, originalElevation);
}
}
}
private static float findMaxElevation(RecyclerView recyclerView, View itemView) {
int childCount = recyclerView.getChildCount();
float max = 0.0F;
for (int i = 0; i < childCount; ++i) {
View child = recyclerView.getChildAt(i);
if (child != itemView) {
float elevation = ViewCompat.getElevation(child);
if (elevation > max) {
max = elevation;
}
}
}
return max;
}
}
RecyclerGridSlipAdapter
public class RecyclerGridSlipAdapter extends RecyclerView.Adapter<RecyclerGridSlipAdapter.ItemViewHolder>
implements ItemTouchHelperAdapter {
private final List<LikeMeDetailEntity> mItems = new ArrayList<>();
private RecyclerView recyclerView;
private Subscription schedule;
private AnimatorSet likeActionAnimationSet;
private AnimatorSet cardAnimationSet;
private int like_num;
public RecyclerGridSlipAdapter() {
}
public void setLike_num(int like_num) {
this.like_num = like_num;
}
public void refreshAllDate(List<LikeMeDetailEntity> dates) {
if (dates != null) {
mItems.clear();
mItems.addAll(dates);
notifyDataSetChanged();
}
}
public void insertDate(int position, LikeMeDetailEntity meDetail) {
if (position <= mItems.size() && meDetail != null) {
mItems.add(position, meDetail);
notifyItemInserted(position);
}
}
@Override
@NonNull
public ItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_like_me, parent, false);
return new ItemViewHolder(view);
}
@SuppressLint("SetTextI18n")
@Override
public void onBindViewHolder(@NonNull final ItemViewHolder holder, int position) {
final int adapterPosition = holder.getAdapterPosition();
final LikeMeDetailEntity detailEntity = mItems.get(adapterPosition);
if (detailEntity != null) {
if (detailEntity.info != null && !TextUtils.isEmpty(detailEntity.info.nick)) {
holder.name.setText(detailEntity.info.nick);
holder.age.setText("," + detailEntity.info.age);
}
if (!TextUtils.isEmpty(detailEntity.distance)) {
holder.distance.setText(detailEntity.distance);
}
if (detailEntity.info != null) {
LoadPicUtils.loadHalfPic(detailEntity.info.portrait, holder.avatar);
}
}
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (ClickUtils.isCommonClick(v) && detailEntity != null && detailEntity.info != null) {
ProfileUiManager.openHomePageActivity(v.getContext(), detailEntity.info.uid, HomePageActivity.BE_LIKE_ME,5);
}
}
});
holder.to_like.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (ClickUtils.isCommonClick(v)) {
if (like_num <= 0) {
ToastUtils.showToast(GlobalContext.getString(R.string.no_like_me_like_time));
return;
}
swipeRight(detailEntity, holder, adapterPosition);
}
}
});
}
@Override
public void onItemDismiss(String action, int position) {
final LikeMeDetailEntity likeMeDetailEntity = mItems.get(position);
mItems.remove(position);
notifyItemRemoved(position);
if (mExecuteListener != null) {
mExecuteListener.onLikeActionCallback(position, likeMeDetailEntity, action);
}
}
@Override
public boolean onItemMove(int fromPosition, int toPosition) {
Collections.swap(mItems, fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
return true;
}
@Override
public void onItemReset(@NonNull RecyclerView.ViewHolder viewHolder, int position) {
//notifyDataSetChanged();
ToastUtils.showToast(GlobalContext.getString(R.string.no_like_me_like_time));
notifyItemChanged(position);
}
@Override
public void onAttachedToRecyclerView(@NonNull RecyclerView recyclerView) {
this.recyclerView = recyclerView;
super.onAttachedToRecyclerView(recyclerView);
}
@Override
public int getItemCount() {
return mItems.size();
}
private static final String TAG = "RecyclerGridSlipAdapter";
/**
* Simple example of a view holder that implements {@link ItemTouchHelperViewHolder} and has a
* "handle" view that initiates a drag event when touched.
*/
public static class ItemViewHolder extends RecyclerView.ViewHolder implements
ItemTouchHelperViewHolder {
public SimpleDraweeView avatar;
public ImageView like;
public ImageView dislike;
public ImageView to_like;
public TextView name;
public TextView age;
public TextView distance;
ItemViewHolder(View itemView) {
super(itemView);
like = itemView.findViewById(R.id.like);
like.setAlpha(0f);
dislike = itemView.findViewById(R.id.dislike);
dislike.setAlpha(0f);
to_like = itemView.findViewById(R.id.to_like);
distance = itemView.findViewById(R.id.distance);
name = itemView.findViewById(R.id.name);
age = itemView.findViewById(R.id.age);
avatar = itemView.findViewById(R.id.avatar);
}
@Override
public void onItemSelected() {
Log.i(TAG, "onItemSelected: ");
}
@Override
public void onItemClear() {
}
}
private LikeExecuteListener mExecuteListener;
public void setExecuteListener(LikeExecuteListener executeListener) {
mExecuteListener = executeListener;
}
private void swipeRight(final LikeMeDetailEntity detailEntity, ItemViewHolder holder, final int position) {
clearAnim();
final int widthPixels = GlobalContext.getDisplayMetrics().widthPixels;
if (mExecuteListener != null) {
mExecuteListener.onLikeAnimExecuteListener(LikeExecuteListener.START);
}
LikeMeItemTouchHelperCallback.takeViewTopInRec(recyclerView, holder, true);
final View itemView = holder.itemView;
final View like = holder.like;
ValueAnimator rotation = ObjectAnimator.ofPropertyValuesHolder(
itemView, PropertyValuesHolder.ofFloat("rotation", 30f));
rotation.setDuration(300);
float trans = itemView.getWidth() + widthPixels;
ValueAnimator translateX = ObjectAnimator.ofPropertyValuesHolder(
itemView, PropertyValuesHolder.ofFloat("translationX", 0f, trans));
ValueAnimator translateY = ObjectAnimator.ofPropertyValuesHolder(
itemView, PropertyValuesHolder.ofFloat("translationY", 0f, DisplayUtil.dip2px(GlobalContext.getAppContext(), 265 * 0.2f)));
translateX.setDuration(500);
translateY.setDuration(500);
cardAnimationSet = new AnimatorSet();
cardAnimationSet.setInterpolator(new AccelerateInterpolator());
cardAnimationSet.playTogether(rotation, translateX, translateY);
cardAnimationSet.start();
ObjectAnimator overlayAnimator = ObjectAnimator.ofFloat(like, "alpha", 0f, 1f);
overlayAnimator.setDuration(300);
likeActionAnimationSet = new AnimatorSet();
likeActionAnimationSet.playTogether(overlayAnimator);
likeActionAnimationSet.start();
cardAnimationSet.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
if (position < mItems.size()) {
mItems.remove(position);
notifyItemRemoved(position);
if (mExecuteListener != null) {
mExecuteListener.onLikeAnimExecuteListener(LikeExecuteListener.END);
mExecuteListener.onLikeActionCallback(position, detailEntity, MatchPairConstant.LIKE_ACTION);
}
} else {
notifyDataSetChanged();
}
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
schedule = AndroidSchedulers.mainThread().createWorker()
.schedule(new Action0() {
@Override
public void call() {
itemView.setRotation(0);
itemView.setTranslationX(0);
itemView.setTranslationY(0);
like.setAlpha(0f);
}
}, 800, TimeUnit.MILLISECONDS);
}
public void release() {
if (schedule != null) {
schedule.unsubscribe();
}
clearAnim();
}
private void clearAnim() {
if (cardAnimationSet != null) {
cardAnimationSet.cancel();
}
if (likeActionAnimationSet != null) {
likeActionAnimationSet.cancel();
}
}
public interface LikeExecuteListener {
int START = 0;
int END = 2;
void onLikeAnimExecuteListener(int status);
void onLikeActionCallback(int position, LikeMeDetailEntity likeDetail, String action);
}
}