RecyclerView 탐색 카드 미끄럼 효과 실현
23638 단어 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="♀ 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;
}
아 이 템 을 드래그 하 는 리 셋 클래스: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>
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
PHP 5.0 개체 모델 깊이 탐색 의 귀속Private 멤버 는 클래스 내부 에 만 존재 합 니 다.Public 와 proctected 멤버 처럼 PHP 는 정적 바 인 딩 을 모 의 합 니 다.예 를 들 어 6.11."Hello there!""I am F...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.