private GridLayout contentView = null;
private TextView menuView = null;
//计算滑动 动画效果
private Scroller mOpenScroller;
private Scroller mCloseScroller;
private int downX;
//记录状态
private int state = STATE_CLOSE;
private static final int STATE_CLOSE = 0;
private static final int STATE_OPEN = 1;
//在关闭滑动的时候计算与父布局的剩余距离
private int mBaseX;
public DelView(Context context) {
this(context,null);
}
public DelView(Context context, AttributeSet attrs) {
this(context, attrs,0);
}
public DelView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
private void initView() {
setOrientation(HORIZONTAL);
View view = LayoutInflater.from(getContext()).inflate(R.layout.pos_item_shop_car,this,true);
contentView = (GridLayout)view.findViewById(R.id.gl_content);
menuView = (TextView) view.findViewById(R.id.tv_del);
mCloseScroller=new Scroller(getContext());
mOpenScroller = new Scroller(getContext());
}
public boolean isOpen() {
return state == STATE_OPEN;
}
public boolean onSwipe(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = (int) event.getX();
break;
case MotionEvent.ACTION_MOVE:
//按下位置减去移动位置 获取移动的距离
int dis = (int) (downX - event.getX());
if (state == STATE_OPEN) {
dis += menuView.getWidth();
}
//移动
move(dis);
break;
case MotionEvent.ACTION_UP:
//当滑到右边视图一半的距离 自动滑进滑出
if ((downX - event.getX()) > (menuView.getWidth() / 2)) {
smoothOpenMenu();
} else {
smoothCloseMenu();
return false;
}
break;
}
//消费掉事件
return true;
}
@Override
public void computeScroll() {
if (state == STATE_OPEN) {
//computeScrollOffset滑动是否结束
if (mOpenScroller.computeScrollOffset()) {
move(mOpenScroller.getCurrX());
postInvalidate();
}
} else {
if (mCloseScroller.computeScrollOffset()) {
move(mBaseX - mCloseScroller.getCurrX());
postInvalidate();
}
}
}
private void move(int dis) {
//这两个判断是为了保证 不要把视图移动过多 导致视图偏移
if (dis > menuView.getWidth()) {
dis = menuView.getWidth();
}
if (dis < 0) {
dis = 0;
}
//view.layout()控制view相对于其父布局的位置 在触发移动的时候调用不断改变位置 完成实际的滑动效果
contentView.layout(-dis, contentView.getTop(), contentView.getWidth() - dis, getMeasuredHeight());
menuView.layout(contentView.getWidth() - dis, menuView.getTop(), contentView.getWidth() + menuView.getWidth() - dis, menuView.getBottom());
}
public void smoothCloseMenu() {
state = STATE_CLOSE;
mBaseX = -contentView.getLeft();
mCloseScroller.startScroll(0, 0, mBaseX, 0, 350);
postInvalidate();
}
public void smoothOpenMenu() {
state = STATE_OPEN;
mOpenScroller.startScroll(-contentView.getLeft(), 0, menuView.getWidth(), 0, 350);
postInvalidate();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if(menuView != null)
menuView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.EXACTLY));
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
//确保centerView menuView的显示位置
if(contentView != null)
contentView.layout(0, 0, getMeasuredWidth(), contentView.getMeasuredHeight());
if(menuView != null)
menuView.layout(getMeasuredWidth(), 0, getMeasuredWidth() + menuView.getMeasuredWidth(), contentView.getMeasuredHeight());
}
==================RecycleView==========================
private DelView mTouchView=null;//记录当前点击的item View
private float mDownX;//x轴坐标
private float mDownY;//y轴坐标
private int mTouchState;//记录点击状态
private int mTouchPosition;//记录点击位置
private static final int TOUCH_STATE_NONE=0; //按下状态
private static final int TOUCH_STATE_X=1;//横滑状态
private static final int TOUCH_STATE_Y=2;//竖滑状态
//判断横竖滑动的最小值
private static final int MAX_Y=5;
private static final int MAX_X=3;
public SlideRecyclerView(@NonNull Context context) {
super(context);
}
public SlideRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
public SlideRecyclerView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() != MotionEvent.ACTION_DOWN && mTouchView == null)
return super.onTouchEvent(ev);
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
//按住的item的position
int oldPosition = mTouchPosition;
//记录位置
mDownX = ev.getX();
mDownY = ev.getY();
mTouchState = TOUCH_STATE_NONE;
//根据当前横纵坐标点获取点击的item的position
mTouchPosition = pointToPosition((int) ev.getX(), (int) ev.getY());
//判断当前点击的是否和上次点击的item是同一个,如果是同一个,并且状态是打开了的就记录状态和坐标
//记录坐标通过Item中的downX属性
if (mTouchPosition == oldPosition && mTouchView != null && mTouchView.isOpen()) {
mTouchState = TOUCH_STATE_X;
mTouchView.onSwipe(ev);
return true;
}
//获取当前的item的View
int index = 0;
if(getLayoutManager() != null){
index = mTouchPosition - ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
}
View currentView = getChildAt(index);
//如果不是同一个item 那么点击的话就关闭掉之前打开的item
if (mTouchView != null && mTouchView.isOpen()) {
mTouchView.smoothCloseMenu();
mTouchView = null;
return super.onTouchEvent(ev);
}
//判断该view的类型
if (currentView instanceof DelView) {
mTouchView = (DelView) currentView;
}
if (mTouchView != null) {
mTouchView.onSwipe(ev);
}
break;
case MotionEvent.ACTION_MOVE:
float dy = Math.abs((ev.getY() - mDownY));
float dx = Math.abs((ev.getX() - mDownX));
if (mTouchState == TOUCH_STATE_X) {
if (mTouchView != null) {
//执行滑动
mTouchView.onSwipe(ev);
}
return true;
} else if (mTouchState == TOUCH_STATE_NONE) {
//判断滑动方向,x方向执行滑动,Y方向执行滚动
if (Math.abs(dy) > MAX_Y) {
mTouchState = TOUCH_STATE_Y;
} else if (dx > MAX_X) {
mTouchState = TOUCH_STATE_X;
}
}
break;
case MotionEvent.ACTION_UP:
//判断状态
if (mTouchState == TOUCH_STATE_X) {
if (mTouchView != null) {
mTouchView.onSwipe(ev);
//如过最后状态是打开 那么就重新初始化
if (!mTouchView.isOpen()) {
mTouchPosition = -1;
mTouchView = null;
}
}
ev.setAction(MotionEvent.ACTION_CANCEL);
super.onTouchEvent(ev);
return true;
}
break;
}
return super.onTouchEvent(ev);
}
private static final int INVALID_POSITION = -1;
private Rect mTouchFrame;
public int pointToPosition(int x, int y) {
int firstPosition = 0;
if(getLayoutManager() != null){
firstPosition = ((LinearLayoutManager) getLayoutManager()).findFirstVisibleItemPosition();
}
Rect frame = mTouchFrame;
if (frame == null) {
mTouchFrame = new Rect();
frame = mTouchFrame;
}
final int count = getChildCount();
for (int i = count - 1; i >= 0; i--) {
final View child = getChildAt(i);
if (child.getVisibility() == View.VISIBLE) {
child.getHitRect(frame);
if (frame.contains(x, y)) {
return firstPosition + i;
}
}
}
return INVALID_POSITION;
}