SlideCardLayoutManager
package com.enjoy.leo_slidecard;
import android.view.View;
import android.view.ViewGroup;
import androidx.recyclerview.widget.RecyclerView;
public class SlideCardLayoutManager extends RecyclerView.LayoutManager {
@Override
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}
@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
detachAndScrapAttachedViews(recycler);
int bottomPosition;
int itemCount = getItemCount();
if (itemCount < CardConfig.MAX_SHOW_COUNT) {
bottomPosition = 0;
} else {
bottomPosition = itemCount - CardConfig.MAX_SHOW_COUNT;
}
for (int i = bottomPosition; i < itemCount; i++) {
View view = recycler.getViewForPosition(i);
addView(view);
measureChildWithMargins(view, 0, 0);
int widthSpace = getWidth() - getDecoratedMeasuredWidth(view);
int heightSpace = getHeight() - getDecoratedMeasuredHeight(view);
layoutDecoratedWithMargins(view, widthSpace / 2, heightSpace / 2,
widthSpace / 2 + getDecoratedMeasuredWidth(view),
heightSpace / 2 + getDecoratedMeasuredHeight(view));
int level = itemCount - i - 1;
if (level > 0) {
if (level < CardConfig.MAX_SHOW_COUNT - 1) {
view.setTranslationY(CardConfig.TRANS_Y_GAP * level);
view.setScaleX(1 - CardConfig.SCALE_GAP * level);
view.setScaleY(1 - CardConfig.SCALE_GAP * level);
} else {
view.setTranslationY(CardConfig.TRANS_Y_GAP * (level - 1));
view.setScaleX(1 - CardConfig.SCALE_GAP * (level - 1));
view.setScaleY(1 - CardConfig.SCALE_GAP * (level - 1));
}
}
}
}
}
SlideCallback
package com.enjoy.leo_slidecard;
import android.graphics.Canvas;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
import com.enjoy.leo_slidecard.adapter.UniversalAdapter;
import java.util.List;
public class SlideCallback extends ItemTouchHelper.SimpleCallback {
private RecyclerView mRv;
private UniversalAdapter<SlideCardBean> adapter;
private List<SlideCardBean> mDatas;
public SlideCallback(RecyclerView mRv,
UniversalAdapter<SlideCardBean> adapter, List<SlideCardBean> mDatas) {
super(0, 15);
this.mRv = mRv;
this.adapter = adapter;
this.mDatas = mDatas;
}
@Override
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder target) {
return false;
}
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int direction) {
SlideCardBean remove = mDatas.remove(viewHolder.getLayoutPosition());
mDatas.add(0, remove);
adapter.notifyDataSetChanged();
}
@Override
public void onChildDraw(@NonNull Canvas c, @NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
double maxDistance = recyclerView.getWidth() * 0.5f;
double distance = Math.sqrt(dX * dX + dY * dY);
double fraction = distance / maxDistance;
if (fraction > 1) {
fraction = 1;
}
int itemCount = recyclerView.getChildCount();
Log.i("SlideCallback",">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
Log.i("SlideCallback",""+distance);
for (int i = 0; i < itemCount; i++) {
Log.i("SlideCallback",""+distance+" "+i);
View view = recyclerView.getChildAt(i);
int level = itemCount - i - 1;
if (level > 0) {
if (level < CardConfig.MAX_SHOW_COUNT - 1) {
view.setTranslationY((float) (CardConfig.TRANS_Y_GAP * level - fraction * CardConfig.TRANS_Y_GAP));
view.setScaleX((float) (1 - CardConfig.SCALE_GAP * level + fraction * CardConfig.SCALE_GAP));
view.setScaleY((float) (1 - CardConfig.SCALE_GAP * level + fraction * CardConfig.SCALE_GAP));
}
}
}
Log.i("SlideCallback","<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<");
}
@Override
public long getAnimationDuration(@NonNull RecyclerView recyclerView, int animationType, float animateDx, float animateDy) {
return 1500;
}
}
CardConfig
public class CardConfig {
public static int MAX_SHOW_COUNT;
public static float SCALE_GAP;
public static int TRANS_Y_GAP;
public static void initConfig(Context context) {
MAX_SHOW_COUNT = 4;
SCALE_GAP = 0.05f;
TRANS_Y_GAP = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 15, context.getResources().getDisplayMetrics());
}
}
MainActivity
package com.enjoy.leo_slidecard;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import android.os.Bundle;
import android.widget.ImageView;
import com.bumptech.glide.Glide;
import com.enjoy.leo_slidecard.adapter.UniversalAdapter;
import com.enjoy.leo_slidecard.adapter.ViewHolder;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private RecyclerView rv;
private UniversalAdapter<SlideCardBean> adapter;
private List<SlideCardBean> mDatas;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
rv = findViewById(R.id.rv);
rv.setLayoutManager(new SlideCardLayoutManager());
mDatas = SlideCardBean.initDatas();
adapter = new UniversalAdapter<SlideCardBean>(this, mDatas, R.layout.item_swipe_card) {
@Override
public void convert(ViewHolder viewHolder, SlideCardBean slideCardBean) {
viewHolder.setText(R.id.tvName, slideCardBean.getName());
viewHolder.setText(R.id.tvPrecent, slideCardBean.getPostition() + "/" + mDatas.size());
Glide.with(MainActivity.this)
.load(slideCardBean.getUrl())
.into((ImageView) viewHolder.getView(R.id.iv));
}
};
rv.setAdapter(adapter);
CardConfig.initConfig(this);
SlideCallback slideCallback = new SlideCallback(rv, adapter, mDatas);
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(slideCallback);
itemTouchHelper.attachToRecyclerView(rv);
}
}