原创:http://blog.csdn.net/lastwarmth/article/details/49831093
手机QQ应该是很普及的App了,看到QQ消息栏对话框列表的每个子项左滑的时候会弹出删除、置顶图标。like this:
于是突发奇想:想要自己实现一个这样的效果。
很显然的,这样的效果实现要依赖Android的事件分发机制,于是我先从Android事件分发入手。对于事件分发还不太熟悉的朋友可以参考Android事件分发机制学习。
下面开工!
首先,针对ListView的每个Item自定义一个MyItemLayout。代码如下:
public class MyItemLayout extends LinearLayout {
private LinearLayout contentView;
private LinearLayout menuView;
private LayoutParams contentLayout;
private boolean isMenuOpen;
private int minLeftMargin;
private int maxLeftMargin = 0;
private Scroller mScroller = null;
public MyItemLayout(Context context, AttributeSet attrs) {
super(context, attrs);
contentLayout = new LayoutParams(getScreenWidth(), LayoutParams.WRAP_CONTENT);
mScroller = new Scroller(context);
}
@Override
public void computeScroll() {
if (mScroller.computeScrollOffset()) {
setLeftMargin(mScroller.getCurrX());
postInvalidate();
}
}
/** * Scroller平滑打开Menu */
public void smoothOpenMenu() {
isMenuOpen = true;
mScroller.startScroll(contentLayout.leftMargin, 0, minLeftMargin - contentLayout.leftMargin, 0, 350);
postInvalidate();
}
/** * Scroller平滑关闭Menu */
public void smoothCloseMenu() {
isMenuOpen = false;
mScroller.startScroll(contentLayout.leftMargin, 0, maxLeftMargin - contentLayout.leftMargin, 0, 350);
postInvalidate();
}
/** * 在布局inflate完成后调用 */
@Override
protected void onFinishInflate() {
super.onFinishInflate();
contentView = (LinearLayout) getChildAt(0);
menuView = (LinearLayout) getChildAt(1);
ViewGroup.LayoutParams lp = menuView.getLayoutParams();
minLeftMargin = -lp.width;
}
/** * 获取屏幕宽度 * @return */
private int getScreenWidth() {
DisplayMetrics dm = getResources().getDisplayMetrics();
return dm.widthPixels;
}
/** * 给contentView设置leftMargin * @param leftMargin */
public void setLeftMargin(int leftMargin) {
if (leftMargin > maxLeftMargin) {
leftMargin = maxLeftMargin;
}
if (leftMargin < minLeftMargin) {
leftMargin = minLeftMargin;
}
contentLayout.leftMargin = leftMargin;
contentView.setLayoutParams(contentLayout);
}
/** * 获取menuView宽度 * @return */
public int getMenuWidth() {
return -minLeftMargin;
}
/** * Menu是否打开 * @return */
public boolean isMenuOpen() {
return isMenuOpen;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
每个Item有2个直接子节点,第一个是contentView,第二个是menuView。通过设置contentView的leftMargin,达到显示Menu的效果。初始时,leftMargin为0,Menu完全隐藏。当滑动时,leftMargin逐渐缩小(因为是负数),当leftMargin等于minLeftMargin时,Menu完全显示。
本来有种想法(参考郭霖大神的博客)是采用线程Sleep的方式来达到滑动效果的。代码如下:
private class ScrollTask extends AsyncTask<Integer, Integer, Integer> {
@Override
protected Integer doInBackground(Integer... speed) {
int leftMargin = contentLayout.leftMargin;
while (true) {
leftMargin = leftMargin - speed[0];
if (leftMargin > maxLeftMargin) {
leftMargin = maxLeftMargin;
break;
}
if (leftMargin < minLeftMargin) {
leftMargin = minLeftMargin;
break;
}
publishProgress(leftMargin);
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
isMenuOpen = speed[0] > 0;
return leftMargin;
}
@Override
protected void onProgressUpdate(Integer... leftMargin) {
contentLayout.leftMargin = leftMargin[0];
contentView.setLayoutParams(contentLayout);
}
@Override
protected void onPostExecute(Integer leftMargin) {
contentLayout.leftMargin = leftMargin;
contentView.setLayoutParams(contentLayout);
}
}
public void toOpenMenu() {
new ScrollTask().execute(30);
}
public void toCloseMenu() {
new ScrollTask().execute(-30);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
但是后面产生的实际效果不太好,滑动的时候总是有点卡顿的感觉,于是便弃用了,后面还是采用的Scroller类。
下面贴上每个Item的布局:
<?xml version="1.0" encoding="utf-8"?>
<com.lastwarmth.mylistview.MyItemLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal">
<LinearLayout android:id="@+id/content" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingBottom="4dp" android:paddingLeft="8dp" android:paddingTop="4dp">
<de.hdodenhof.circleimageview.CircleImageView android:id="@+id/profile_image" android:layout_width="56dp" android:layout_height="56dp" app:civ_border_color="#FF000000" app:civ_border_width="1dp" />
<LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:layout_marginLeft="16dp" android:layout_marginTop="4dp" android:orientation="vertical">
<TextView android:id="@+id/group_name" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="群名称" />
<TextView android:id="@+id/qq_content" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:singleLine="true" android:text="聊天内容" />
</LinearLayout>
</LinearLayout>
<LinearLayout android:id="@+id/menu" android:layout_width="240dp" android:layout_height="match_parent" android:orientation="horizontal">
<TextView android:id="@+id/to_top" style="@style/menu_text_style" android:layout_width="80dp" android:layout_height="match_parent" android:background="@android:color/darker_gray" android:gravity="center" android:text="置顶" />
<TextView android:id="@+id/had_read" style="@style/menu_text_style" android:layout_width="80dp" android:layout_height="match_parent" android:background="@android:color/holo_orange_light" android:gravity="center" android:text="标为已读" />
<TextView android:id="@+id/delete" style="@style/menu_text_style" android:layout_width="80dp" android:layout_height="match_parent" android:background="@android:color/holo_red_light" android:gravity="center" android:text="删除" />
</LinearLayout>
</com.lastwarmth.mylistview.MyItemLayout>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
content id即是第一个子节点,menu id为第二个子节点。
下面贴出Adapter的代码:
public class MyAdapter extends BaseAdapter {
private List<MyModel> data;
private Context mContext;
public MyAdapter(List<MyModel> data, Context mContext) {
this.data = data;
this.mContext = mContext;
}
@Override
public int getCount() {
if (data != null) {
return data.size();
}
return 0;
}
@Override
public Object getItem(int position) {
if (data != null) {
return data.get(position);
}
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
@Override
public View getView(final int position, View contentView, ViewGroup parent) {
ViewHolder holder;
if (contentView == null) {
holder = new ViewHolder();
contentView = LayoutInflater.from(mContext).inflate(R.layout.list_item, parent, false);
holder.imageView = (CircleImageView) contentView.findViewById(R.id.profile_image);
holder.groupName = (TextView) contentView.findViewById(R.id.group_name);
holder.content = (TextView) contentView.findViewById(R.id.qq_content);
holder.toTop = (TextView) contentView.findViewById(R.id.to_top);
holder.hadRead = (TextView) contentView.findViewById(R.id.had_read);
holder.delete = (TextView) contentView.findViewById(R.id.delete);
contentView.setTag(holder);
} else {
holder = (ViewHolder) contentView.getTag();
}
MyModel myModel = (MyModel) getItem(position);
holder.groupName.setText(myModel.getGroupName());
holder.content.setText(myModel.getContent());
Picasso.with(mContext)
.load(myModel.getImageUrl())
.placeholder(R.mipmap.lb_zjtx)
.into(holder.imageView);
final MyItemLayout finalContentView = (MyItemLayout) contentView;
holder.toTop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext, "已置顶", Toast.LENGTH_SHORT).show();
finalContentView.smoothCloseMenu();
}
});
holder.hadRead.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(mContext, "已阅读", Toast.LENGTH_SHORT).show();
finalContentView.smoothCloseMenu();
}
});
holder.delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
data.remove(position);
finalContentView.smoothCloseMenu();
notifyDataSetChanged();
Toast.makeText(mContext, "已删除", Toast.LENGTH_SHORT).show();
}
});
return contentView;
}
private static class ViewHolder {
CircleImageView imageView;
TextView groupName;
TextView content;
TextView toTop;
TextView hadRead;
TextView delete;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
Adapter类比较简单,这里不做过多的赘述
MyModel类主要是为了模仿QQ会话写的一个类。
public class MyModel {
String imageUrl;
String groupName;
String content;
public MyModel(String imageUrl, String groupName, String content) {
this.imageUrl = imageUrl;
this.groupName = groupName;
this.content = content;
}
public String getImageUrl() {
return imageUrl;
}
public String getGroupName() {
return groupName;
}
public String getContent() {
return content;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
下面便是最关键的一个:自定义ListView,覆写onTouchEvent方法,实现滑动删除。
public class MyListView extends ListView {
private VelocityTracker mVelocityTracker;
private float xDown;
private float yDown;
private int MAX_Y = 5;
private int MAX_X = 3;
private int mTouchPosition;
private MyItemLayout mTouchView;
private int mTouchState = TOUCH_STATE_NONE;
private static final int TOUCH_STATE_NONE = 0;
private static final int TOUCH_STATE_X = 1;
private static final int TOUCH_STATE_Y = 2;
public MyListView(Context context, AttributeSet attrs) {
super(context, attrs);
MAX_X = dp2px(MAX_X);
MAX_Y = dp2px(MAX_Y);
}
/** * 创建VelocityTracker对象,并将触摸事件加入到VelocityTracker当中 * * @param event */
private void createVelocityTracker(MotionEvent event) {
if (mVelocityTracker == null) {
mVelocityTracker = VelocityTracker.obtain();
}
mVelocityTracker.addMovement(event);
}
/** * 获取手指在滑动的速度 * * @return 滑动速度,以每秒钟移动了多少像素值为单位 */
private int getScrollVelocity() {
mVelocityTracker.computeCurrentVelocity(1000);
int velocity = (int) mVelocityTracker.getXVelocity();
return Math.abs(velocity);
}
/** * 回收VelocityTracker对象 */
private void recycleVelocityTracker() {
mVelocityTracker.recycle();
mVelocityTracker = null;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return super.onInterceptTouchEvent(ev);
}
/** * 触摸事件的控制 * * @param ev * @return */
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() != MotionEvent.ACTION_DOWN && mTouchView == null) {
return super.onTouchEvent(ev);
}
createVelocityTracker(ev);
float moveX;
float moveY;
int action = ev.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
int prevPosition = mTouchPosition;
xDown = ev.getX();
yDown = ev.getY();
mTouchState = TOUCH_STATE_NONE;
mTouchPosition = pointToPosition((int) xDown, (int) yDown);
if (prevPosition == mTouchPosition && mTouchView != null && mTouchView.isMenuOpen()) {
mTouchState = TOUCH_STATE_X;
return true;
}
View view = getChildAt(mTouchPosition - getFirstVisiblePosition());
if (mTouchView != null && mTouchView.isMenuOpen()) {
mTouchView.smoothCloseMenu();
mTouchView = null;
return false;
}
if (view instanceof MyItemLayout) {
mTouchView = (MyItemLayout) view;
}
break;
case MotionEvent.ACTION_MOVE:
moveX = ev.getX() - xDown;
moveY = ev.getY() - yDown;
if (mTouchState == TOUCH_STATE_X) {
if (!mTouchView.isMenuOpen()) {
mTouchView.setLeftMargin((int) moveX);
} else {
mTouchView.setLeftMargin((int) (moveX - mTouchView.getMenuWidth()));
}
return true;
} else if (mTouchState == TOUCH_STATE_NONE) {
if (Math.abs(moveY) > MAX_Y) {
mTouchState = TOUCH_STATE_Y;
} else if (Math.abs(moveX) > MAX_X) {
mTouchState = TOUCH_STATE_X;
}
}
break;
case MotionEvent.ACTION_UP:
moveX = ev.getX() - xDown;
if (mTouchState == TOUCH_STATE_X) {
if (-moveX > mTouchView.getMenuWidth() / 2 || (moveX < 0 && getScrollVelocity() > 200)) {
if (!mTouchView.isMenuOpen()) {
mTouchView.smoothOpenMenu();
}
} else {
mTouchView.smoothCloseMenu();
mTouchView = null;
mTouchPosition = -1;
}
recycleVelocityTracker();
return true;
}
break;
}
return super.onTouchEvent(ev);
}
private int dp2px(int dp) {
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
getContext().getResources().getDisplayMetrics());
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
在这个项目中,触摸事件分以下几种情况:
1、当前没有Menu正在显示
- ACTION_DOWN记录相关信息,准备接收ACTION_MOVE、ACTION_UP事件。
- ACTION_MOVE中,判断是横滑还是竖滑。若是横滑,则调用setLeftMargin(),这个时候若一直滑动,Menu会慢慢地显示出来。后面会返回true,主要是为了拦截最后的super.onTouchEvent(ev)不执行。若是竖滑,则直接调用super.onTouchEvent(ev),这个时候若一直滑动,则是ListView的上下滑动了。
- ACTION_UP中,我们只需要判断是否要显示,若显示则调用smoothOpenMenu(),并返回true(这里返回true或者false都没有实际的意义)。若是不需要,则直接super.onTouchEvent(ev)。
2、当前有Menu正在显示
- ACTION_DOWN,若当前点击的Item不是Menu正在显示的Item,那么直接smoothCloseMenu(),并且返回false。返回false后MOVE、UP等事件会统统不接收。
- 若是正在点击的Item,那么首先设置为横滑,并且返回true,等待后续的触摸事件。
- ACTION_MOVE因为在DOWN的时候设置了mTouchState = TOUCH_STATE_X;那么会执行到if内部,因为Menu正在显示,所以不会调用setLeftMargin(),并且直接返回true,即后面的super.onTouchEvent(ev)也不会调用。
- ACTION_UP中判断Menu是否要关闭,若关闭则调用smoothCloseMenu(),并且返回true。若是不需要,则直接返回super.onTouchEvent(ev)。
这里是复杂的地方,需要对各种情况进行判断,然后执行相应的逻辑。我写了好多次,改过好多次QAQ…
注意:
- 在ACTION_DOWN的分支中,返回false会直接截断后面MOVE、UP等事件的接收。
- 在ACTION_MOVE与ACTION_UP的返回值,为true为false,并没有特别实际的效果,仅仅是为了返回,以此来截断super.onTouchEvent(ev)的执行。
下面上效果图:
看起来效果也还不错,是吧?