效果:
触摸:按下,移动,抬起
点击:一组触摸事件的组合(按下,松开)
长按:一组触摸事件的组合(按下,持续超过500ms(Android中))
为一个View设置点击事件:
view.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { Log.i("", "onClick"); } });
为一个View设置touch事件:
view.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Log.i("", "ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.i("", "ACTION_MOVE"); break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: Log.i("", "ACTION_UP"); break; } return false; } });
当同时为一个View设置点击和touch事件时:
在onTouch返回false时:
当onTouch返回true时:
不在响应点击事件了
我们的需求是,在item关闭时可以响应点击事件(onTouch中返回false),在item打开时不响应点击事件(onTouch中返回true)
下面处理Touch事件:
ACTION_DOWN: 记录下手指按下的位置 ACTION_MOVE: 判断移动的距离(带正负号)移动item ACTION_UP:根据手指抬起位置,将视图移动到合适的位置
listView 的 item 的布局
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/layout" android:layout_width="match_parent" android:layout_height="86dp" android:layout_below="@+id/Listview" > <TextView android:id="@+id/more" android:layout_width="60dp" android:layout_height="match_parent" android:layout_toLeftOf="@+id/delete" android:background="@android:color/darker_gray" android:clickable="true" android:gravity="center" android:onClick="more" android:text="更多" android:textColor="@android:color/white" android:textSize="16sp" /> <TextView android:id="@+id/delete" android:layout_width="60dp" android:layout_height="match_parent" android:layout_alignParentRight="true" android:background="@android:color/holo_red_light" android:clickable="true" android:gravity="center" android:onClick="delete" android:text="删除" android:textColor="@android:color/white" android:textSize="16sp" /> <TextView android:id="@+id/tv_top" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/holo_orange_dark" android:gravity="center" android:text="item" android:textSize="20sp" /> </RelativeLayout>
自定义的View
package com.zyh.slideview; import android.animation.Animator; import android.animation.Animator.AnimatorListener; import android.animation.ObjectAnimator; import android.content.Context; import android.util.AttributeSet; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; public class MoveLayout extends RelativeLayout implements OnClickListener { private Context context; private int downX; private TextView tv_top; private TextView delete; private TextView more; public MoveLayout(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); init(context); } public MoveLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MoveLayout(Context context) { this(context, null); } private void init(Context context) { this.context = context; LayoutInflater.from(context).inflate(R.layout.move_layout, this, true); delete = (TextView) findViewById(R.id.delete); more = (TextView) findViewById(R.id.more); tv_top = (TextView) findViewById(R.id.tv_top); tv_top.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { return handlerTouch(v, event); } }); tv_top.setOnClickListener(this); more.setOnClickListener(this); delete.setOnClickListener(this); } /* ---------------------处理 Touch-------------------------- */ boolean result = false; boolean isOpen = false; protected boolean handlerTouch(View v, MotionEvent event) { int bottomWidth = delete.getWidth() + delete.getWidth(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // Log.i("", "ACTION_DOWN"); downX = (int) event.getRawX(); break; case MotionEvent.ACTION_MOVE: // Log.i("", "ACTION_MOVE"); // if (isAniming) // break; int dx = (int) (event.getRawX() - downX); // Log.i("", "dy___" + dx); if (isOpen) { // 打开状态 // 向右滑动 if (dx > 0 && dx < bottomWidth) { v.setTranslationX(dx - bottomWidth); // 允许移动,阻止点击 result = true; } } else { // 闭合状态 // 向左移动 if (dx < 0 && Math.abs(dx) < bottomWidth) { v.setTranslationX(dx); // 允许移动,阻止点击 result = true; } } break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: // Log.i("", "ACTION_UP" + v.getTranslationX()); // 获取已经移动的 float ddx = v.getTranslationX(); // 判断打开还是关闭 if (ddx <= 0 && ddx > -(bottomWidth / 2)) { // 关闭 ObjectAnimator oa1 = ObjectAnimator.ofFloat(v, "translationX", ddx, 0).setDuration(100); oa1.start(); oa1.addListener(new AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { isOpen = false; result = false; } @Override public void onAnimationCancel(Animator animation) { isOpen = false; result = false; } }); } if (ddx <= -(bottomWidth / 2) && ddx > -bottomWidth) { // 打开 ObjectAnimator oa1 = ObjectAnimator.ofFloat(v, "translationX", ddx, -bottomWidth) .setDuration(100); oa1.start(); result = true; isOpen = true; } break; } return result; } @Override public void onClick(View v) { switch (v.getId()) { case R.id.tv_top: Toast.makeText(context, "item", 0).show(); break; case R.id.more: Toast.makeText(context, "more", 0).show(); break; case R.id.delete: Toast.makeText(context, "delete", 0).show(); break; } } }
源代码:github](https://github.com/18236887539/SlideLayout)