Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

添加卡片回退功能 #28

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 29 additions & 3 deletions app/src/main/java/com/yuqirong/cardswipeview/MainActivity.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Toast;

Expand All @@ -17,12 +18,15 @@
import me.yuqirong.cardswipelayout.CardConfig;
import me.yuqirong.cardswipelayout.CardItemTouchHelperCallback;
import me.yuqirong.cardswipelayout.CardLayoutManager;
import me.yuqirong.cardswipelayout.CardRecyclerView;
import me.yuqirong.cardswipelayout.OnSwipeListener;


public class MainActivity extends AppCompatActivity {
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

private List<Integer> list = new ArrayList<>();
private CardItemTouchHelperCallback<Integer> cardCallback;
private CardRecyclerView recyclerView;

@Override
protected void onCreate(Bundle savedInstanceState) {
Expand All @@ -33,10 +37,17 @@ protected void onCreate(Bundle savedInstanceState) {
}

private void initView() {
final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
ImageButton likeButton = (ImageButton) findViewById(R.id.like_button);
ImageButton hateButton = (ImageButton) findViewById(R.id.hate_button);
ImageButton backButton = (ImageButton) findViewById(R.id.back_button);
likeButton.setOnClickListener(this);
hateButton.setOnClickListener(this);
backButton.setOnClickListener(this);

recyclerView = (CardRecyclerView) findViewById(R.id.recyclerView);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(new MyAdapter());
CardItemTouchHelperCallback cardCallback = new CardItemTouchHelperCallback(recyclerView.getAdapter(), list);
cardCallback = new CardItemTouchHelperCallback(recyclerView, recyclerView.getAdapter(), list);
cardCallback.setOnSwipedListener(new OnSwipeListener<Integer>() {

@Override
Expand Down Expand Up @@ -91,6 +102,21 @@ private void initData() {
list.add(R.drawable.img_avatar_07);
}

@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.like_button:
cardCallback.handleCardSwipe(CardConfig.SWIPING_RIGHT, 300L);
break;
case R.id.hate_button:
cardCallback.handleCardSwipe(CardConfig.SWIPING_LEFT, 300L);
break;
case R.id.back_button:
cardCallback.handlerCardBack(300L);
break;
}
}

private class MyAdapter extends RecyclerView.Adapter {
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
9 changes: 9 additions & 0 deletions app/src/main/res/drawable/ic_reply_black_24dp.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M10,9V5l-7,7 7,7v-4.1c5,0 8.5,1.6 11,5.1 -1,-5 -4,-10 -11,-11z"/>
</vector>
5 changes: 5 additions & 0 deletions app/src/main/res/drawable/img_buttons_hate_selector.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/img_buttons_hate_pressed" android:state_pressed="true" />
<item android:drawable="@drawable/img_buttons_hate_normal" />
</selector>
5 changes: 5 additions & 0 deletions app/src/main/res/drawable/img_buttons_like_selector.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8" ?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/img_buttons_like_pressed" android:state_pressed="true" />
<item android:drawable="@drawable/img_buttons_like_normal" />
</selector>
46 changes: 44 additions & 2 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,51 @@
android:orientation="vertical"
tools:context="com.yuqirong.cardswipeview.MainActivity">

<android.support.v7.widget.RecyclerView
<me.yuqirong.cardswipelayout.CardRecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
android:layout_height="0dp"
android:layout_weight="1" />

<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:orientation="horizontal"
android:layout_marginTop="10dp"
android:layout_marginBottom="20dp">

<ImageButton
android:id="@+id/hate_button"
android:layout_width="65dp"
android:layout_height="65dp"
android:background="@null"
android:scaleType="centerInside"
android:src="@drawable/img_buttons_hate_selector" />

<Space
android:layout_width="12dp"
android:layout_height="wrap_content" />

<ImageButton
android:id="@+id/like_button"
android:layout_width="65dp"
android:layout_height="65dp"
android:background="@null"
android:scaleType="centerInside"
android:src="@drawable/img_buttons_like_selector" />

<Space
android:layout_width="12dp"
android:layout_height="wrap_content" />

<ImageButton
android:id="@+id/back_button"
android:layout_width="65dp"
android:layout_height="65dp"
android:background="@null"
android:scaleType="centerInside"
android:src="@drawable/ic_reply_black_24dp" />

</LinearLayout>
</LinearLayout>
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package me.yuqirong.cardswipelayout;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.graphics.Canvas;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.helper.ItemTouchHelper;
import android.view.View;
import android.view.animation.Interpolator;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

/**
Expand All @@ -17,13 +23,42 @@ public class CardItemTouchHelperCallback<T> extends ItemTouchHelper.Callback {
private final RecyclerView.Adapter adapter;
private List<T> dataList;
private OnSwipeListener<T> mListener;
private CardRecyclerView recyclerView;
ValueAnimator swipeAnimator;
//需要撤回的View列表
List<ReturnView> mLastReturnList = new ArrayList<>();
//需要添加道卡片的列表
List<T> needAddLastList = new ArrayList<>();

public CardItemTouchHelperCallback(@NonNull RecyclerView.Adapter adapter, @NonNull List<T> dataList) {
this.adapter = checkIsNull(adapter);
this.dataList = checkIsNull(dataList);
public int getReturnSize(){
return mLastReturnList.size();
}

public void addData(T data) {
needAddLastList.add(data);
}

public static class ReturnView<T> {

RecyclerView.ViewHolder viewHolder;
Integer direction;
T curData;

public ReturnView(RecyclerView.ViewHolder viewHolder, Integer direction, T data) {
this.viewHolder = viewHolder;
this.direction = direction;
this.curData = data;
}

}

public CardItemTouchHelperCallback(@NonNull CardRecyclerView recyclerView, @NonNull RecyclerView.Adapter adapter, @NonNull List<T> dataList) {
this(recyclerView, adapter, dataList, null);
}

public CardItemTouchHelperCallback(@NonNull RecyclerView.Adapter adapter, @NonNull List<T> dataList, OnSwipeListener<T> listener) {
public CardItemTouchHelperCallback(@NonNull CardRecyclerView recyclerView, @NonNull RecyclerView.Adapter adapter,
@NonNull List<T> dataList, OnSwipeListener<T> listener) {
this.recyclerView = checkIsNull(recyclerView);
this.adapter = checkIsNull(adapter);
this.dataList = checkIsNull(dataList);
this.mListener = listener;
Expand Down Expand Up @@ -63,12 +98,20 @@ public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
int layoutPosition = viewHolder.getLayoutPosition();
T remove = dataList.remove(layoutPosition);
adapter.notifyDataSetChanged();

mLastReturnList.add(new ReturnView(viewHolder,direction,remove));
if (mListener != null) {
mListener.onSwiped(viewHolder, remove, direction == ItemTouchHelper.LEFT ? CardConfig.SWIPED_LEFT : CardConfig.SWIPED_RIGHT);
}

// 当没有数据时回调 mListener
if (adapter.getItemCount() == 0) {
if (mListener != null) {
if(needAddLastList.size() > 0) {
dataList.addAll(needAddLastList);
needAddLastList.clear();
mLastReturnList.clear();
adapter.notifyDataSetChanged();
}else if (mListener != null) {
mListener.onSwipedClear();
}
}
Expand Down Expand Up @@ -133,4 +176,101 @@ private float getThreshold(RecyclerView recyclerView, RecyclerView.ViewHolder vi
return recyclerView.getWidth() * getSwipeThreshold(viewHolder);
}

public T handlerCardBack(long duration) {
if(mLastReturnList.isEmpty()) {
Toast.makeText(recyclerView.getContext(),"当前不可返回",Toast.LENGTH_SHORT).show();
return null;
}

final ReturnView returnView = mLastReturnList.remove(mLastReturnList.size()-1);

// 移除 onTouchListener,否则触摸滑动会乱了
RecyclerView.ViewHolder topHolder = recyclerView.findViewHolderForAdapterPosition(0);
if(topHolder != null&&topHolder.itemView != null) {
topHolder.itemView.setOnTouchListener(null);
}

dataList.add(0, (T) returnView.curData);
adapter.notifyDataSetChanged();

if (swipeAnimator != null && swipeAnimator.isStarted()) {
return null;
}
final CardRecyclerView recyclerView = checkIsNull(this.recyclerView);
final Canvas canvas = checkIsNull(this.recyclerView.getCanvas());
if (returnView.viewHolder == null) {
return null;
}
if (returnView.direction == CardConfig.SWIPING_LEFT) {
swipeAnimator = ValueAnimator.ofFloat(-recyclerView.getWidth() / 2, 0);
} else if (returnView.direction == CardConfig.SWIPING_RIGHT) {
swipeAnimator = ValueAnimator.ofFloat(recyclerView.getWidth() / 2, 0);
} else {
throw new IllegalStateException("flag must be one of SWIPING_LEFT or SWIPING_RIGHT");
}
swipeAnimator.setDuration(duration);
swipeAnimator.setInterpolator(null);
swipeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {

float value = (float) animation.getAnimatedValue();
onChildDraw(canvas, recyclerView, returnView.viewHolder, value, 0, ItemTouchHelper.ACTION_STATE_SWIPE, false);
}
});
swipeAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
// onSwiped(returnView.viewHolder, returnView.direction == CardConfig.SWIPING_LEFT ? ItemTouchHelper.LEFT : ItemTouchHelper.RIGHT);
}
});
swipeAnimator.start();

return (T) returnView.curData;

}

public void handleCardSwipe(int flag, long duration) {
handleCardSwipe(flag, duration, null);
}

public void handleCardSwipe(final int flag, long duration, Interpolator interpolator) {
if (swipeAnimator != null && swipeAnimator.isStarted()) {
return;
}
final CardRecyclerView recyclerView = checkIsNull(this.recyclerView);
final Canvas canvas = checkIsNull(this.recyclerView.getCanvas());
final RecyclerView.ViewHolder viewHolder = recyclerView.findViewHolderForAdapterPosition(0);
if (viewHolder == null) {
return;
}
if (flag == CardConfig.SWIPING_LEFT) {
swipeAnimator = ValueAnimator.ofFloat(0, -recyclerView.getWidth() / 2);
} else if (flag == CardConfig.SWIPING_RIGHT) {
swipeAnimator = ValueAnimator.ofFloat(0, recyclerView.getWidth() / 2);
} else {
throw new IllegalStateException("flag must be one of SWIPING_LEFT or SWIPING_RIGHT");
}
swipeAnimator.setDuration(duration);
swipeAnimator.setInterpolator(interpolator);
swipeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {

float value = (float) animation.getAnimatedValue();
onChildDraw(canvas, recyclerView, viewHolder, value, 0, ItemTouchHelper.ACTION_STATE_SWIPE, true);
}
});
swipeAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
onSwiped(viewHolder, flag == CardConfig.SWIPING_LEFT ? ItemTouchHelper.LEFT : ItemTouchHelper.RIGHT);
clearView(recyclerView, viewHolder);
}
});
swipeAnimator.start();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package me.yuqirong.cardswipelayout;

import android.content.Context;
import android.graphics.Canvas;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;

public class CardRecyclerView extends RecyclerView {

private Canvas canvas;

public CardRecyclerView(Context context) {
super(context);
}

public CardRecyclerView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}

public CardRecyclerView(Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}

@Override
public void onDraw(Canvas c) {
this.canvas = c;
super.onDraw(c);
}

public Canvas getCanvas() {
return canvas;
}
}