Android控件拖动以及控件的onTouch事件与onClick事件的冲突问题

一:

原理就是响应控件的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:

你可能感兴趣的:(Android控件拖动以及控件的onTouch事件与onClick事件的冲突问题)