RecyclerView实现探探卡片滑动效果

发布时间:2019-08-08 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了RecyclerView实现探探卡片滑动效果脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

这里是一个通过自定义view和自定义RecyclerView的:layoutManager,再结合ITemTouchHelPEr实现的一个仿探探的卡片滑动的效果:

RecyclerView实现探探卡片滑动效果

效果图已经奉上,接下来是代码:

首先是每张图片的布局:item

 <LinearLayout XMlns:andROId="http://schemas.android.COM/apk/res/android"  xMLns:app="http://schemas.android.com/apk/res-auto"  android:layout_width="336dp"  android:layout_height="426dp"  android:background="@drawable/img_card_background"  android:gravity="center"  android:orientation="vertical">    <RelativeLayout   android:layout_width="match_parent"   android:layout_height="0dp"   android:layout_weight="1">     <com.bwie.w.test1121.cardswipelayout.RoundImageView    android:id="@+id/iv_avatar"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:scaleType="centerCrop"    android:src="@drawable/img_avatar_01"    app:radius="7.5dp" />     <ImageView    android:id="@+id/iv_dislike"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:layout_alignParentRight="true"    android:layout_marginRight="15dp"    android:layout_marginTop="15dp"    android:alpha="0"    android:src="@drawable/img_dislike" />     <ImageView    android:id="@+id/iv_like"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:layout_marginLeft="15dp"    android:layout_marginTop="15dp"    android:alpha="0"    android:src="@drawable/img_like" />    </RelativeLayout>    <RelativeLayout   android:layout_width="match_parent"   android:layout_height="100dp"   android:paddingLeft="14dp"   android:paddingTop="15dp">     <TextView    android:id="@+id/tv_name"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:gravity="center"    android:text="小姐姐"    android:textColor="@android:color/black"    android:textSize="16sp" />     <TextView    android:id="@+id/tv_age"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:layout_below="@id/tv_name"    android:layout_marginTop="5dp"    android:background="@drawable/Shape_age"    android:gravity="center"    android:text="&#x2640; 23"    android:textColor="#FFFFFF"    android:textSize="14sp" />     <TextView    android:id="@+id/tv_constellation"    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:layout_below="@id/tv_name"    android:layout_marginLeft="4dp"    android:layout_marginTop="5dp"    android:layout_toRightOf="@id/tv_age"    android:background="@drawable/shape_constellation"    android:gravity="center"    android:text="狮子座"    android:textColor="#FFFFFF"    android:textSize="14sp" />     <TextView    android:layout_width="wrap_content"    android:layout_height="wrap_content"    android:layout_below="@id/tv_age"    android:layout_marginTop="5dp"    android:gravity="center"    android:text="IT/互联网"    android:textColor="#cbcbcb" />    </RelativeLayout>     </LinearLayout>

activity_main:

 <android.support.v7.widget.RecyclerView   android:id="@+id/recyclerView"   android:layout_width="match_parent"   android:layout_height="match_parent" />

一个常量参数类: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 CardItemTouchHelperCallback<T> extends ItemTouchHelper.Callback {    PRivate final RecyclerView.Adapter adapter;  private List<T> dataList;  private OnSwipeListener<T> mListener;    public CardItemTouchHelperCallback(@NonNull RecyclerView.Adapter adapter, @NonNull List<T> dataList) {   this.adapter = checkIsNull(adapter);   this.dataList = checkIsNull(dataList);  }    public CardItemTouchHelperCallback(@NonNull RecyclerView.Adapter adapter, @NonNull List<T> dataList, OnSwipeListener<T> listener) {   this.adapter = checkIsNull(adapter);   this.dataList = checkIsNull(dataList);   this.mListener = listener;  }    private <T> T checkIsNull(T t) {   if (t == null) {    throw new NullPointerException();   }   return t;  }    public void setOnSwipedListener(OnSwipeListener<T> 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> 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<T> {    /**   * 卡片还在滑动时回调   *   * @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<Integer> 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<Integer>() {      @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:

 <resources>  <declare-styleable name="RoundImageView">   <attr name="radius" format="reference|dimension" />  </declare-styleable> </resources>
android教程
脚本网站
android studio

脚本宝典总结

以上是脚本宝典为你收集整理的RecyclerView实现探探卡片滑动效果全部内容,希望文章能够帮你解决RecyclerView实现探探卡片滑动效果所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。