使用RecyclerView怎么实现探探卡片滑动效果
本篇文章给大家分享的是有关使用RecyclerView怎么实现探探卡片滑动效果,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。

为阜新等地区用户提供了全套网页设计制作服务,及阜新网站建设行业解决方案。主营业务为网站制作、网站建设、阜新网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!
首先是每张图片的布局:item
activity_main:
一个常量参数类:CardConfig
/**
* 常量参数
*/
public final class CardConfig {
/**
* 显示可见的卡片数量
*/
public static final int DEFAULT_SHOW_ITEM = 3;
/**
* 默认缩放的比例
*/
public static final float DEFAULT_SCALE = 0.1f;
/**
* 卡片Y轴偏移量时按照14等分计算
*/
public static final int DEFAULT_TRANSLATE_Y = 14;
/**
* 卡片滑动时默认倾斜的角度
*/
public static final float DEFAULT_ROTATE_DEGREE = 15f;
/**
* 卡片滑动时不偏左也不偏右
*/
public static final int SWIPING_NONE = 1;
/**
* 卡片向左滑动时
*/
public static final int SWIPING_LEFT = 1 << 2;
/**
* 卡片向右滑动时
*/
public static final int SWIPING_RIGHT = 1 << 3;
/**
* 卡片从左边滑出
*/
public static final int SWIPED_LEFT = 1;
/**
* 卡片从右边滑出
*/
public static final int SWIPED_RIGHT = 1 << 2;
}拖动item的回调类:CardItemTouchHelperCallBack
public class CardItemTouchHelperCallbackextends ItemTouchHelper.Callback { private final RecyclerView.Adapter adapter; private List dataList; private OnSwipeListener mListener; public CardItemTouchHelperCallback(@NonNull RecyclerView.Adapter adapter, @NonNull List dataList) { this.adapter = checkIsNull(adapter); this.dataList = checkIsNull(dataList); } public CardItemTouchHelperCallback(@NonNull RecyclerView.Adapter adapter, @NonNull List dataList, OnSwipeListener listener) { this.adapter = checkIsNull(adapter); this.dataList = checkIsNull(dataList); this.mListener = listener; } private T checkIsNull(T t) { if (t == null) { throw new NullPointerException(); } return t; } public void setOnSwipedListener(OnSwipeListener mListener) { this.mListener = mListener; } /** * 设置滑动类型标记 * * @param recyclerView * @param viewHolder * @return * 返回一个整数类型的标识,用于判断Item那种移动行为是允许的 */ @Override public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { int dragFlags = 0; int swipeFlags = 0; RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager(); if (layoutManager instanceof CardLayoutManager) { swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; } return makeMovementFlags(dragFlags, swipeFlags); } /** * 拖拽切换Item的回调 * * @param recyclerView * @param viewHolder * @param target * @return * 如果Item切换了位置,返回true;反之,返回false */ @Override public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, RecyclerView.ViewHolder target) { return false; } /** * * 划出时会执行 * @param viewHolder * @param direction:左侧划出为:4,右侧划出为:8 */ @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { Log.d("mylog", "onSwiped: " + direction); // 移除 onTouchListener,否则触摸滑动会乱了 viewHolder.itemView.setOnTouchListener(null); int layoutPosition = viewHolder.getLayoutPosition(); T remove = dataList.remove(layoutPosition); adapter.notifyDataSetChanged(); if (mListener != null) { mListener.onSwiped(viewHolder, remove, direction == ItemTouchHelper.LEFT ? CardConfig.SWIPED_LEFT : CardConfig.SWIPED_RIGHT); } // 当没有数据时回调 mListener if (adapter.getItemCount() == 0) { if (mListener != null) { mListener.onSwipedClear(); } } } /** * Item是否支持滑动 * * @return * true 支持滑动操作 * false 不支持滑动操作 */ @Override public boolean isItemViewSwipeEnabled() { return false; } /** * 拖动时会执行的方法 * @param c * @param recyclerView * @param viewHolder * @param dX * @param dY * @param actionState * @param isCurrentlyActive */ @Override 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); // Log.d("mylog", "onChildDraw: 拖动"); View itemView = viewHolder.itemView; if (actionState == ItemTouchHelper.ACTION_STATE_SWIPE) { float ratio = dX / getThreshold(recyclerView, viewHolder); // ratio 最大为 1 或 -1 if (ratio > 1) { ratio = 1; } else if (ratio < -1) { ratio = -1; } Log.d("mylog", "onChildDraw: " + ratio); itemView.setRotation(ratio * CardConfig.DEFAULT_ROTATE_DEGREE); int childCount = recyclerView.getChildCount(); // 当数据源个数大于最大显示数时 if (childCount > CardConfig.DEFAULT_SHOW_ITEM) { for (int position = 1; position < childCount - 1; position++) { int index = childCount - position - 1; View view = recyclerView.getChildAt(position); view.setScaleX(1 - index * CardConfig.DEFAULT_SCALE + Math.abs(ratio) * CardConfig.DEFAULT_SCALE); view.setScaleY(1 - index * CardConfig.DEFAULT_SCALE + Math.abs(ratio) * CardConfig.DEFAULT_SCALE); /* view.setScaleX(1 - index * CardConfig.DEFAULT_SCALE ); view.setScaleY(1 - index * CardConfig.DEFAULT_SCALE);*/ view.setTranslationY((index - Math.abs(ratio)) * itemView.getMeasuredHeight() / CardConfig.DEFAULT_TRANSLATE_Y); } } else { // 当数据源个数小于或等于最大显示数时 for (int position = 0; position < childCount - 1; position++) { int index = childCount - position - 1; View view = recyclerView.getChildAt(position); view.setScaleX(1 - index * CardConfig.DEFAULT_SCALE + Math.abs(ratio) * CardConfig.DEFAULT_SCALE); view.setScaleY(1 - index * CardConfig.DEFAULT_SCALE + Math.abs(ratio) * CardConfig.DEFAULT_SCALE); view.setTranslationY((index - Math.abs(ratio)) * itemView.getMeasuredHeight() / CardConfig.DEFAULT_TRANSLATE_Y); } } if (mListener != null) { if (ratio != 0) { // Log.d("mylog", "onChildDraw: 不为零"); mListener.onSwiping(viewHolder, ratio, ratio < 0 ? CardConfig.SWIPING_LEFT : CardConfig.SWIPING_RIGHT); } else { // Log.d("mylog", "onChildDraw: 为零"); mListener.onSwiping(viewHolder, ratio, CardConfig.SWIPING_NONE); } } } } @Override public void clearView(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { super.clearView(recyclerView, viewHolder); viewHolder.itemView.setRotation(0f); } private float getThreshold(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) { return recyclerView.getWidth() * getSwipeThreshold(viewHolder); } }
自定义布局管理器:CardLayoutManager:
/**
* 自定义布局管理器
*/
public class CardLayoutManager extends RecyclerView.LayoutManager {
private RecyclerView mRecyclerView;
private ItemTouchHelper mItemTouchHelper;
public CardLayoutManager(@NonNull RecyclerView recyclerView, @NonNull ItemTouchHelper itemTouchHelper) {
this.mRecyclerView = checkIsNull(recyclerView);
this.mItemTouchHelper = checkIsNull(itemTouchHelper);
}
private T checkIsNull(T t) {
if (t == null) {
throw new NullPointerException();
}
return t;
}
@Override
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
@Override
public void onLayoutChildren(final RecyclerView.Recycler recycler, RecyclerView.State state) {
detachAndScrapAttachedViews(recycler);
int itemCount = getItemCount();
// 当数据源个数大于最大显示数时
if (itemCount > CardConfig.DEFAULT_SHOW_ITEM) {
for (int position = CardConfig.DEFAULT_SHOW_ITEM; position >= 0; position--) {
final View view = recycler.getViewForPosition(position);
addView(view);
measureChildWithMargins(view, 0, 0);
int widthSpace = getWidth() - getDecoratedMeasuredWidth(view);
int heightSpace = getHeight() - getDecoratedMeasuredHeight(view);
// recyclerview 布局
layoutDecoratedWithMargins(view, widthSpace / 2, heightSpace / 2,
widthSpace / 2 + getDecoratedMeasuredWidth(view),
heightSpace / 2 + getDecoratedMeasuredHeight(view));
if (position == CardConfig.DEFAULT_SHOW_ITEM) {
view.setScaleX(1 - (position - 1) * CardConfig.DEFAULT_SCALE);
view.setScaleY(1 - (position - 1) * CardConfig.DEFAULT_SCALE);
view.setTranslationY((position - 1) * view.getMeasuredHeight() / CardConfig.DEFAULT_TRANSLATE_Y);
} else if (position > 0) {
view.setScaleX(1 - position * CardConfig.DEFAULT_SCALE);
view.setScaleY(1 - position * CardConfig.DEFAULT_SCALE);
view.setTranslationY(position * view.getMeasuredHeight() / CardConfig.DEFAULT_TRANSLATE_Y);
} else {
view.setOnTouchListener(mOnTouchListener);
}
}
} else {
// 当数据源个数小于或等于最大显示数时
for (int position = itemCount - 1; position >= 0; position--) {
final View view = recycler.getViewForPosition(position);
addView(view);
measureChildWithMargins(view, 0, 0);
int widthSpace = getWidth() - getDecoratedMeasuredWidth(view);
int heightSpace = getHeight() - getDecoratedMeasuredHeight(view);
// recyclerview 布局
layoutDecoratedWithMargins(view, widthSpace / 2, heightSpace / 2,
widthSpace / 2 + getDecoratedMeasuredWidth(view),
heightSpace / 2 + getDecoratedMeasuredHeight(view));
if (position > 0) {
view.setScaleX(1 - position * CardConfig.DEFAULT_SCALE);
view.setScaleY(1 - position * CardConfig.DEFAULT_SCALE);
view.setTranslationY(position * view.getMeasuredHeight() / CardConfig.DEFAULT_TRANSLATE_Y);
} else {
view.setOnTouchListener(mOnTouchListener);
}
}
}
}
private View.OnTouchListener mOnTouchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
RecyclerView.ViewHolder childViewHolder = mRecyclerView.getChildViewHolder(v);
if (MotionEventCompat.getActionMasked(event) == MotionEvent.ACTION_DOWN) {
mItemTouchHelper.startSwipe(childViewHolder);
}
return false;
}
};
} 状态回调接口:OnSwipeListener
/** * @author 状态回调接口 */ public interface OnSwipeListener{ /** * 卡片还在滑动时回调 * * @param viewHolder 该滑动卡片的viewHolder * @param ratio 滑动进度的比例 * @param direction 卡片滑动的方向,CardConfig.SWIPING_LEFT 为向左滑,CardConfig.SWIPING_RIGHT 为向右滑, * CardConfig.SWIPING_NONE 为不偏左也不偏右 */ void onSwiping(RecyclerView.ViewHolder viewHolder, float ratio, int direction); /** * 卡片完全滑出时回调 * * @param viewHolder 该滑出卡片的viewHolder * @param t 该滑出卡片的数据 * @param direction 卡片滑出的方向,CardConfig.SWIPED_LEFT 为左边滑出;CardConfig.SWIPED_RIGHT 为右边滑出 */ void onSwiped(RecyclerView.ViewHolder viewHolder, T t, int direction); /** * 所有的卡片全部滑出时回调 */ void onSwipedClear(); }
自定义条目图片样式:RoundImageView:
/**
* 自定义图片样式,顶部圆角显示
*/
public class RoundImageView extends ImageView {
private Path mPath;
private RectF mRectF;
/*圆角的半径,依次为左上角xy半径,右上角,右下角,左下角*/
private float[] rids = new float[8];
private PaintFlagsDrawFilter paintFlagsDrawFilter;
public RoundImageView(Context context) {
this(context, null);
}
public RoundImageView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public RoundImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.RoundImageView);
float mRadius = array.getDimension(R.styleable.RoundImageView_radius, 10);
rids[0] = mRadius;
rids[1] = mRadius;
rids[2] = mRadius;
rids[3] = mRadius;
rids[4] = 0f;
rids[5] = 0f;
rids[6] = 0f;
rids[7] = 0f;
array.recycle();
//用于绘制的类
mPath = new Path();
//抗锯齿
paintFlagsDrawFilter = new PaintFlagsDrawFilter(0, Paint.ANTI_ALIAS_FLAG | Paint.FILTER_BITMAP_FLAG);
//关闭硬件加速,同时其他地方依然享受硬件加速
setLayerType(View.LAYER_TYPE_HARDWARE, null);
}
@Override
protected void onDraw(Canvas canvas) {
// Log.d("mylog", "onDraw: ");
//重置path
mPath.reset();
//p1:大小,p2:圆角,p3:CW:顺时针绘制path,CCW:逆时针
mPath.addRoundRect(mRectF, rids, Path.Direction.CW);
//添加抗锯齿
canvas.setDrawFilter(paintFlagsDrawFilter);
canvas.save();
//该方法不支持硬件加速,如果开启会导致效果出不来,所以之前设置关闭硬件加速
//Clip(剪切)的时机:通常理解的clip(剪切),是对已经存在的图形进行clip的。
// 但是,在android上是对canvas(画布)上进行clip的,要在画图之前对canvas进行clip,
// 如果画图之后再对canvas进行clip不会影响到已经画好的图形。一定要记住clip是针对canvas而非图形
//开始根据path裁剪
canvas.clipPath(mPath);
super.onDraw(canvas);
canvas.restore();
}
int a,b;
//执行在onDraw()之前
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
// Log.d("mylog", "onSizeChanged: ");
a = w;
b = h;
mRectF = new RectF(0, 0, w, h);
Log.d("mylog", "onSizeChanged: "+w+"-----"+h);
}
}MainActivity:
public class MainActivity extends AppCompatActivity {
private List list = new ArrayList<>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
initData();
}
private void initView() {
final RecyclerView recyclerView = findViewById(R.id.recyclerView);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(new MyAdapter());
CardItemTouchHelperCallback cardCallback = new CardItemTouchHelperCallback(recyclerView.getAdapter(), list);
cardCallback.setOnSwipedListener(new OnSwipeListener() {
@Override
public void onSwiping(RecyclerView.ViewHolder viewHolder, float ratio, int direction) {
MyAdapter.MyViewHolder myHolder = (MyAdapter.MyViewHolder) viewHolder;
viewHolder.itemView.setAlpha(1 - Math.abs(ratio) * 0.2f);
if (direction == CardConfig.SWIPING_LEFT) {
myHolder.dislikeImageView.setAlpha(Math.abs(ratio));
} else if (direction == CardConfig.SWIPING_RIGHT) {
myHolder.likeImageView.setAlpha(Math.abs(ratio));
} else {
myHolder.dislikeImageView.setAlpha(0f);
myHolder.likeImageView.setAlpha(0f);
}
}
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, Integer o, int direction) {
MyAdapter.MyViewHolder myHolder = (MyAdapter.MyViewHolder) viewHolder;
viewHolder.itemView.setAlpha(1f);
myHolder.dislikeImageView.setAlpha(0f);
myHolder.likeImageView.setAlpha(0f);
Toast.makeText(MainActivity.this, direction == CardConfig.SWIPED_LEFT ? "swiped left" : "swiped right", Toast.LENGTH_SHORT).show();
}
@Override
public void onSwipedClear() {
Toast.makeText(MainActivity.this, "data clear", Toast.LENGTH_SHORT).show();
recyclerView.postDelayed(new Runnable() {
@Override
public void run() {
initData();
recyclerView.getAdapter().notifyDataSetChanged();
}
}, 3000L);
}
});
final ItemTouchHelper touchHelper = new ItemTouchHelper(cardCallback);
final CardLayoutManager cardLayoutManager = new CardLayoutManager(recyclerView, touchHelper);
recyclerView.setLayoutManager(cardLayoutManager);
touchHelper.attachToRecyclerView(recyclerView);
}
private void initData() {
list.add(R.drawable.img_avatar_01);
list.add(R.drawable.img_avatar_02);
list.add(R.drawable.img_avatar_03);
list.add(R.drawable.img_avatar_04);
list.add(R.drawable.img_avatar_05);
list.add(R.drawable.img_avatar_06);
list.add(R.drawable.img_avatar_07);
}
private class MyAdapter extends RecyclerView.Adapter {
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item, parent, false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
ImageView avatarImageView = ((MyViewHolder) holder).avatarImageView;
avatarImageView.setImageResource(list.get(position));
}
@Override
public int getItemCount() {
return list.size();
}
class MyViewHolder extends RecyclerView.ViewHolder {
ImageView avatarImageView;
ImageView likeImageView;
ImageView dislikeImageView;
MyViewHolder(View itemView) {
super(itemView);
avatarImageView = (ImageView) itemView.findViewById(R.id.iv_avatar);
likeImageView = (ImageView) itemView.findViewById(R.id.iv_like);
dislikeImageView = (ImageView) itemView.findViewById(R.id.iv_dislike);
}
}
}
} attrs:
以上就是使用RecyclerView怎么实现探探卡片滑动效果,小编相信有部分知识点可能是我们日常工作会见到或用到的。希望你能通过这篇文章学到更多知识。更多详情敬请关注创新互联行业资讯频道。
网页标题:使用RecyclerView怎么实现探探卡片滑动效果
网站链接:http://www.scyingshan.cn/article/gsdsso.html


咨询
建站咨询
