2014-02-25 50 views
0

我有一個按鈕,我可以在任何地方將其拖動到屏幕上,但它會在屏幕外的同時拖動,所以如何拖動只有裏面的畫面,因此,它不應該走出屏幕的拖動按鈕正在屏幕外?

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; 
     } 
    }); 

回答

1

首先,使用方法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 

} 
+1

感謝您的回答.....我應該在哪裏做這些if和else if?在MotionEvent.Action_Move中?請爲我詳細介紹一下im新的android。這裏是什麼deltaX? – sachin

+0

如果我刪除「layoutParams.rightMargin = -250; layoutParams.bottomMargin = -250;」這兩個我的按鈕不會離開屏幕底部和右側,但我的按鈕會縮小拖動底部和右邊 – sachin

+0

嗨Sachin,是的,你需要將這些If/Else條件放在你的'ACTION_MOVE'情況下。而且我沒有得到關於佈局利潤率的第二個問題。你能否詳細說明一下? – Saket

1

而註冊只是爲了回答這個問題,因爲發現相同的,不幸的是錯的無奈,回答所有在互聯網上。

要處理你的對象被認爲外面抽,設立爲對象的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); 
       } 
      } 
     } 
    } 
}; 
4

修改OnTouch listerner部分爲:

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