一:
原理就是响应控件的Touch事件,在Touch事件中对移动进行处理,如果没效果那你试着在布局文件中设置控件的 android:clickable="true"。
当然,大部分人都是直接想要解决方案,这里直接贴代码,后面会有一些说明。
-
1.首先在 你的 Activity 实现 OnTouchListener 接口 ,并重写onTouch 方法
implements OnTouchListener
-
2.activity中定义几个变量先
private int screenWidth, screenHeight;
private int lastX, lastY,moveDownX;
private ImageView mTestIV; -
3.在Activity 的 onCreate方法中
mTestIV=(ImageView) findViewById(R.id.iv_test); mTestIV.setOnTouchListener(this); Display dis = this.getWindowManager().getDefaultDisplay(); screenWidth = dis.getWidth(); screenHeight = dis.getHeight();
-
4.重写onTouch内部方法
@Override public boolean onTouch(View v, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { lastX = (int) event.getRawX(); lastY = (int) event.getRawY(); moveDownX= (int) event.getRawX(); } if (event.getAction() == MotionEvent.ACTION_MOVE){ int dx = (int) event.getRawX() - lastX; int dy = (int) event.getRawY() - lastY; int top = v.getTop() + dy; int left = v.getLeft() + dx; if (top <= 0) { top = 0; } if (top >= screenHeight - mTestIV.getHeight()) { top = screenHeight - mTestIV.getHeight(); } if (left >= screenWidth - mTestIV.getWidth()) { left = screenWidth - mTestIV.getWidth(); } if (left <= 0) { left = 0; } v.layout(left, top, left + mTestIV.getWidth(), top + mTestIV.getHeight()); lastX = (int) event.getRawX(); lastY = (int) event.getRawY(); } if (event.getAction() == MotionEvent.ACTION_UP) { int tempDX = (int) event.getRawX() - moveDownX; if (Math.abs(tempDX) < 6) { // do your things return false;// 距离较小,当作click事件来处理 } } return true;// 返回true,不执行click事件 }
以上为全部代码。
二:
现在我们来分析下实现步骤:
一:我们开始要实现控件拖动效果
原理比较简单:
- 1.在按下的时候(MotionEvent.ACTION_DOWN),开始记录当前按下位置的坐标值;
- 2.然后在手指移动控件的时候(MotionEvent.ACTION_MOVE),不断计算当前的位置的坐标并重绘控件的位置
这里说明下 一些知识点:
视图的left , top , right , bottom 的值是针对其父视图的相对位置,left相当于X轴值, top相当于Y轴值(原点为该widget 的父控件的左上角的点)
getX是获取以widget左上角为坐标原点计算的X轴坐标值
getRawX 获取的是以屏幕左上角为坐标原点计算的X轴坐标值
做完以上步骤,可以实现正常的拖动,但这时候会发现,你拖动抬起手指后会执行onClick事件。
现在分析下这件事出现的原因:
在Android中,对一个View同时调用OnTouch事件和OnClick事件时,导致事件冲突。
比如onClick事件打算执行A动作,OnTouch事件打算执行B动作,但是在实际使用时会发现,当调用OnTouch时,有可能会同时执行A,B两个动作,这是因为OnClick事件本身就是在OnTouch事件中发生的;
在onTouch事件中,如果返回true,就不会执行onClick,返回false,就同时执行onClick方法,要想把OnTouch和onClick事件完全的区分。可能过下列方法,解决该冲突问题:
就是在 OnTouch中的MotionEvent.ACTION_DOWN 时,记录下点(X1,Y1),在 MotionEvent.ACTION_UP 时,记录下点(X2,Y2),然后比对 俩点之间的距离,如果小于一个较小数值(比如6),就认为是Click事件,onTouch中返回false,如果距离较大,可以当作onTouch事件去处理,返回true:
网友评论