4.左滑最后版
2017-03-16 本文已影响21人
crossroads
前言
根据启舰大大 的博客所学习的滑动删除。
大家应该也发现了,如果你手指一直按着不动,会有微小的滑动,导致左滑,明明此刻不向左滑的~~~(>_<)~~~而且,点击事件都要哭了,这一节我们的目标就把这些bug君消灭了。
消灭微小滑动bug君
这里,我们介绍一个int值
int mScaleTouchSlop = ViewConfiguration.get(context.getApplicationContext()).getScaledTouchSlop();
这个值表示滑动的时候,手的移动要大于这个距离才开始移动控件。
int lastX;
@Override
public boolean onTouchEvent(MotionEvent event) {
int scrollX = getScrollX();
int newScrooll;
if (event.getAction() == MotionEvent.ACTION_MOVE) {
if (Math.abs(lastX - event.getX()) < mScaleTouchSlop) {
return true;
}
else {
newScrooll = (int) (scrollX + lastX - event.getX());
if (newScrooll < 0) newScrooll = 0;
else if (newScrooll > delWidth) newScrooll = delWidth;
scrollTo(newScrooll, 0);
}
}
else if (event.getAction() == MotionEvent.ACTION_UP) {
if (scrollX > delWidth / 2)
newScrooll = delWidth;
else
newScrooll = 0;
scroller.startScroll(scrollX, 0, newScrooll - scrollX, 0);
//用invalidate()来重绘,由于我们这里有Scroller,所以在重绘时就会走到VIEW的computeScroll()函数
invalidate();
}
lastX = (int) event.getX();
return true;
}
@Override
public void computeScroll() {
//computeScrollOffset()来判断当前Scroller的状态——是否已经计算移动位置结束,
// 如果结束返回FALSE,如果还在计算就返回TRUE
if (scroller.computeScrollOffset()) {
scrollTo(scroller.getCurrX(), scroller.getCurrY());
//如果仍在计算,就调用invalidate,使之重新进入computeScroll方法
invalidate();
}
}
效果图
为点击事件开路
如果在touch事件中处理的话,是不可能的=_=
如果判断是点击事件还是滑动事件,一定得根据手指的移动距离判断,就是move事件中,但是只有down事件返回false/super,才会走click事件。但是也只有down事件返回true,才会走move。
所以我们不能在touch事件中判断,那么这里用dispatchTouchEvent来判断是不是滑动。
效果图
代码如下:
boolean isMoved = false;
float lastX, firstX;
public boolean dispatchTouchEvent(MotionEvent ev) {
int newScrooll;
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
isMoved = false;
firstX = lastX = ev.getRawX();
return super.dispatchTouchEvent(ev);
case MotionEvent.ACTION_MOVE:
newScrooll = (int) (getScrollX() + lastX - ev.getX());
if (newScrooll < 0) newScrooll = 0;
else if (newScrooll > delWidth) newScrooll = delWidth;
scrollTo(newScrooll, 0);
if (Math.abs(firstX - ev.getRawX()) > mScaleTouchSlop) {
isMoved = true;
}
case MotionEvent.ACTION_UP:
lastX = ev.getRawX();
//当展开状态
if (getScrollX() > mScaleTouchSlop) {
//如果不是移动并且点击区域在item区域,而不是删除区域的话
if (!isMoved && ev.getX() < getWidth() - getScrollX()) {
scroller.startScroll(getScrollX(), 0, -getScrollX(), 0);
invalidate();
return true;
}
}
int scrollX = getScrollX();
if (scrollX > delWidth / 2)
newScrooll = delWidth;
else
newScrooll = 0;
scroller.startScroll(scrollX, 0, newScrooll - scrollX, 0);
//用invalidate()来重绘,由于我们这里有Scroller,所以在重绘时就会走到VIEW的computeScroll()函数
invalidate();
//移动或者有滚动则不响应click
if (isMoved) {
return true;
}
break;
default:
break;
}
lastX = ev.getX();
return super.dispatchTouchEvent(ev);
}
@Override
public void computeScroll() {
//computeScrollOffset()来判断当前Scroller的状态——是否已经计算移动位置结束,
// 如果结束返回FALSE,如果还在计算就返回TRUE
if (scroller.computeScrollOffset()) {
scrollTo(scroller.getCurrX(), scroller.getCurrY());
//如果仍在计算,就调用invalidate,使之重新进入computeScroll方法
invalidate();
}
}
View item = findViewById(R.id.item);
item.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "item", Toast.LENGTH_SHORT).show();
}
});
del = findViewById(R.id.del);
del.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(getApplicationContext(), "删除", Toast.LENGTH_SHORT).show();
}
});
<com.crossroads.demo.demo.DelView
android:id="@+id/itemroot"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="@color/colorPrimaryDark"
android:orientation="horizontal"
>
<TextView
android:id="@+id/item"
android:layout_width="match_parent"
android:layout_height="100dp"
android:background="@color/colorAccent"
android:gravity="center"
android:text="ITEM"
/>
<TextView
android:id="@+id/del"
android:layout_width="60dp"
android:layout_height="100dp"
android:gravity="center"
android:text="删除"
/>
</com.crossroads.demo.demo.DelView>
另一种实现方式
效果图这个是利用intercept来决定是否将事件拦截,是github某位大神的实现方式,但是我忘记是哪位大神的了,没有找到链接,非常抱歉~
下面是部分代码
private static boolean isTouch = false;
private boolean isUserSwiped;
private float lastX, firstX;
boolean isUnMoved;
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
isUnMoved = true;
isUserSwiped = false;
if (isTouch) {
return false;
}
else
isTouch = true;
firstX = ev.getRawX();
lastX = firstX;
break;
case MotionEvent.ACTION_MOVE:
float scrollerX = lastX - ev.getRawX();
if (Math.abs(getScrollX()) > 10 || Math.abs(scrollerX) > 10)
getParent().requestDisallowInterceptTouchEvent(true);
scrollBy((int) (scrollerX), 0);
if (getScrollX() > delWidth) {
scrollTo(delWidth, 0);
}
else if (getScrollX() < 0) {
scrollTo(0, 0);
}
if (Math.abs(scrollerX) > mScaleTouchSlop) {
isUnMoved = false;
}
lastX = ev.getRawX();
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
if (Math.abs(ev.getRawX() - firstX) > mScaleTouchSlop) {
isUserSwiped = true;
}
if (Math.abs(getScrollX()) >= delWidth / 2) {
expandAnimate();
}
else {
closeAnimate();
}
isTouch = false;
break;
default:
break;
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {
case MotionEvent.ACTION_MOVE:
if (Math.abs(ev.getRawX() - firstX) > mScaleTouchSlop)
return true;
break;
case MotionEvent.ACTION_CANCEL:
case MotionEvent.ACTION_UP:
if (Math.abs(getScrollX()) > mScaleTouchSlop) {
if (ev.getX() < getWidth() - getScrollX()) {
if (isUnMoved)
closeAnimate();
return true;
}
}
if (isUserSwiped) return true;
break;
default:
break;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean performLongClick() {
if (Math.abs(getScrollX()) > mScaleTouchSlop) {
return false;
}
return super.performLongClick();
}
public void closeAnimate() {
if (expandValueAnim != null && expandValueAnim.isRunning()) expandValueAnim.cancel();
closeAnimator = ValueAnimator.ofInt(getScrollX(), 0);
closeAnimator.setDuration(300);
closeAnimator.start();
closeAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
scrollTo((Integer) animation.getAnimatedValue(), 0);
}
});
}
ValueAnimator closeAnimator;
ValueAnimator expandValueAnim;
private void expandAnimate() {
if (closeAnimator != null && closeAnimator.isRunning()) closeAnimator.cancel();
expandValueAnim = ValueAnimator.ofInt(getScrollX(), delWidth);
expandValueAnim.setInterpolator(new OvershootInterpolator());
expandValueAnim.setDuration(300);
expandValueAnim.start();
expandValueAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
scrollTo((Integer) animation.getAnimatedValue(), 0);
}
});
}