【问题标题】:Dragging button is going out of the screen?拖动按钮要离开屏幕了吗?
【发布时间】:2014-02-25 13:37:36
【问题描述】:

我有一个按钮,可以拖到屏幕的任意位置,但是拖的时候会到屏幕外,所以怎么只拖到屏幕里面,才不会拖到屏幕外

Button.setOnTouchListener(new TextView.OnTouchListener() {
        public boolean onTouch(View view, MotionEvent event) {              

            X_button = (int) event.getRawX();
            Y_button= (int) event.getRawY();


            switch (event.getAction() & MotionEvent.ACTION_MASK) {
            case MotionEvent.ACTION_DOWN:

                RelativeLayout.LayoutParams lParams = (RelativeLayout.LayoutParams) view.getLayoutParams();
                _xDelta = X_button - lParams.leftMargin;
                _yDelta = Y_button - lParams.topMargin;
                break;
            case MotionEvent.ACTION_UP:                 
                 if(!isMoving)
                 {
                    view.performClick();                        
                 }  

                 isMoving=false;
                break;
            case MotionEvent.ACTION_POINTER_DOWN:
                break;
            case MotionEvent.ACTION_POINTER_UP:
                break;
            case MotionEvent.ACTION_MOVE:                   
                isMoving=true;                  
                RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view
                        .getLayoutParams();
                layoutParams.leftMargin = X_button - _xDelta;
                layoutParams.topMargin = Y_button - _yDelta;
                layoutParams.rightMargin = -250;
                layoutParams.bottomMargin = -250;
                view.setLayoutParams(layoutParams);

                break;
            }
            return true;
        }
    });

【问题讨论】:

    标签: android ontouchlistener


    【解决方案1】:

    将 OnTouch 监听器部分修改为:

     DisplayMetrics displaymetrics = new DisplayMetrics();
     getWindowManager().getDefaultDisplay().getMetrics(displaymetrics);
     screenHight = displaymetrics.heightPixels;
     screenWidth = displaymetrics.widthPixels;
    
      @SuppressLint("NewApi") @Override
      public boolean onTouch(View view, MotionEvent event) {
    
    
           float newX, newY;
    
        switch (event.getActionMasked()) {
          case MotionEvent.ACTION_DOWN:
    
            dX = view.getX() - event.getRawX();
            dY = view.getY() - event.getRawY();
            lastAction = MotionEvent.ACTION_DOWN;
            break;
    
          case MotionEvent.ACTION_MOVE:
    
              newX = event.getRawX() + dX;
              newY = event.getRawY() + dY;
    
          // check if the view out of screen
              if ((newX <= 0 || newX >= screenWidth-view.getWidth()) || (newY <= 0 || newY >= screenHight-view.getHeight()))
              {
                  lastAction = MotionEvent.ACTION_MOVE;
                  break;      
              }
    
            view.setX(newX);
            view.setY(newY);
    
            lastAction = MotionEvent.ACTION_MOVE;
    
            break;
    
          case MotionEvent.ACTION_UP:
            if (lastAction == MotionEvent.ACTION_DOWN)
              Toast.makeText(DraggableView.this, "Clicked!", Toast.LENGTH_SHORT).show();
            break;
    
          default:
            return false;
        }
        return true;
      }
    

    请参考此解决方案,当拖动图像时,图像会停留在屏幕上。 https://stackoverflow.com/a/36417605/4324288

    【讨论】:

      【解决方案2】:

      首先,使用View.setX()View.setY()View.setTranslateX()View.setTranslateY()方法在屏幕上移动视图,而不是更新LayoutParams的边距。我发现它们的表现更流畅。

      其次,为了将视图限制为可用窗口,请使用以下函数获取可用窗口大小:

      DisplayMetrics metrics = getResources().getDisplayMetrics();
      int windowWidth = metrics.widthPixels;
      int windowHeight = metrics.heightPixels
      

      接下来,在您的 onTouch 方法中,计算目标位置是否超过上述尺寸。例如:

      if( currentXLocation + deltaX > windowWidth ){
      
          // this will ensure that target location 
          // is always <= windowHeight
          deltaX = windowWidth - currentXLocation; 
      
      } else if( currentXLocation + deltaX < 0){
      
          deltaX = -(currentXLocation);
      
      } else if (...){
      
          // perform similar calculations for the rest 
      
      }
      

      【讨论】:

      • 感谢您的回答.....如果和其他如果在 MotionEvent.Action_Move 中,我应该在哪里做这些?请详细解释我,因为我是 android 新手。什么是 deltaX?​​span>
      • 如果我删除“layoutParams.rightMargin = -250; layoutParams.bottomMargin = -250;”这两个我的按钮不会离开屏幕底部和右侧,但我的按钮会在拖动底部和右侧时缩小
      • 嗨,Sachin,是的,您需要将这些 If/Else 条件放在您的 ACTION_MOVE 案例中。我没有得到你关于布局边距的第二个问题。能否请您进一步详细说明?
      • 感谢我将它放在 ACTION_MOVE 中,我应用了其他逻辑并且它起作用了
      【解决方案3】:

      注册只是为了回答这个问题,因为在整个互联网上发现相同的,不幸的是错误的答案感到沮丧。

      要处理在视图之外绘制的对象,请为对象设置 OnDragListener,然后从那里调用处理程序 - 如果不使用处理程序,它将崩溃 - 并将视图 ID 传递给处理程序。除了,我发现您的用户还可以通过同时触摸两个按钮来搞砸工作,并且当您切换活动时,如果用户正在触摸屏幕,那么您也可以通过这种方式丢失对象 - 所以最有效的是我的从拖动侦听器 ACTION_DRAG_ENDED 调用处理程序,触摸侦听器 ACTION_UP 只是确保应该可见的所有内容都是。这样,每次用户停止触摸屏幕时,它都会修复他/她所做的一切。

      private final class MyTouchListener implements OnTouchListener {
          @Override
          public boolean onTouch(View view, MotionEvent motionEvent) {
              switch (motionEvent.getAction()) {
                  case MotionEvent.ACTION_DOWN:
                      ClipData data = ClipData.newPlainText("", "");
                      DragShadowBuilder shadowBuilder = new DragShadowBuilder(view);
                      view.startDrag(data, shadowBuilder, view, 0);
                      view.setVisibility(View.INVISIBLE);
                      return true;
                  case MotionEvent.ACTION_UP:
                      drophandler.sendEmptyMessage(0);
                  case MotionEvent.ACTION_MOVE:
                      return true;
                  default:
                      break;
                  }
              return true;
          }
      }
      
      class MyDragListener implements OnDragListener {
          @Override
          public boolean onDrag(View v, DragEvent event) {
              View view = (View) event.getLocalState();
              Button drag = (Button) view;
              int action = event.getAction();
      
              switch (event.getAction()) {
                  case DragEvent.ACTION_DRAG_STARTED:
                      break;
                  case DragEvent.ACTION_DRAG_ENTERED:
                      break;
                  case DragEvent.ACTION_DRAG_EXITED:
                      break;
                  case DragEvent.ACTION_DROP:
                      Button target = (Button) v;
                      //do stuff
                      return true;
                  case DragEvent.ACTION_DRAG_ENDED:
                      drophandler.sendEmptyMessage(0);
                      return true;
                  default:
                      break;
              }
              return true;
          }
      }
      
      private Handler drophandler = new Handler() {
          public void handleMessage(android.os.Message msg) {
              for(int x = 0; x < 3 + difficulty; x++){
                  for(int y = 0; y < 5 + difficulty; y++){
                      if (buttons[x][y] != null){
                          buttons[x][y].setVisibility(View.VISIBLE);
                      }
                  }
              }
          }
      };
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-12-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多