【参考链接】
以如下应用场景为例,在FrameLayout中有一个MyTextView,当手指在MyTextView上触摸时,MyTextView随着手指而移动。
主要是事件处理结合《View的长宽及其在父ViewGroup中的位置,如何改变?》中的方法来使用
此外,如果该View设置了onClickListener,则在手指离开屏幕ACTION_UP以后还会触发onClickListener
如果希望发生拖动时不触发onClick,可以增加一个变量来控制
public class MyTextView extends TextView {
private int lastX;
private int lastY;
private boolean callOnClick=true;
public MyTextView(Context context) {
super(context);
init();
}
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init(){
setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if(callOnClick)
Toast.makeText(getContext(), "onClick!", Toast.LENGTH_SHORT).show();
}
});
}
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);//for onClick/onLongClick
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
lastX=(int) event.getRawX();
lastY= (int) event.getRawY();
callOnClick=true;
break;
case MotionEvent.ACTION_MOVE:
int newX= (int) event.getRawX();
int newY= (int) event.getRawY();
int deltaX=newX-lastX;
int deltaY=newY-lastY;
//这里就不加了,不然拖动的断断续续
// int touchSlop=ViewConfiguration.get(this.getContext()).getScaledTouchSlop();
// if(Math.abs(deltaX)>touchSlop || Math.abs(deltaY)>touchSlop){
//因为这个例子中FrameLayout里面只有这个MyTextView,所以可以用setLayoutParams()实现效果
//并且不要求改变大小,所以也可以用layout()实现
// FrameLayout.LayoutParamsparams=(FrameLayout.LayoutParams)this.getLayoutParams();
// params.leftMargin+=deltaX;
// params.topMargin+=deltaY;
// setLayoutParams(params);
// requestLayout();
layout(getLeft()+deltaX, getTop()+deltaY, getRight()+deltaX, getBottom()+deltaY);
//更新坐标
lastX=newX;
lastY=newY;
// }
callOnClick=false;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
lastX=(int) event.getRawX();
lastY= (int) event.getRawY();
callOnClick=true;
break;
default:
break;
}
return true;
}
}