Android簡易實戰教程--第五十二話《滿屏拖動的控件2》

之前就有寫過這種小Demo,那裏是使用setLayoutParams給控件設置新座標的方式完成的,有興趣讀者可以參考博客:Android簡易實戰教程--第四十九話《滿屏拖動的控件》

本篇小Demo,使用另一種實現方式同樣完成類似的功能。

在開始之前,你需要複習一下有關座標的知識:

int getLeft()
得到當前視圖左頂點相對父視圖的X軸座標
int getTop()
得到當前視圖左頂點相對父視圖的Y軸座標
int getRight()
得到當前視圖右下角點相對父視圖的X軸座標
int getBottom()
得到當前視圖右下角點相對父視圖的Y軸座標
layout(int left, int top, int right, int bottom) :
動態指定當前視圖在父視圖中的定位, 參數爲相對父視圖的座標
ViewParent getParent() :
得到當前View的父視圖對象

getX():    得到控件相對自己座標X值 

getY():    得到控件相對自己座標Y值 

getRawX():    得到控件相對父容器座標X值 

getRawY():    得到控件相對父容器座標Y值

這個東西很簡單,直接上Demo代碼:



寫的很詳細,相信沒有什麼問題。咱們再看看代碼:

public class MainActivity extends AppCompatActivity 
implements View.OnTouchListener {

   private ImageView mImageView;

   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       
setContentView(R.layout.activity_main);
       
mImageView = (ImageView) findViewById(R.id.iv_main);
       
mImageView.setOnTouchListener(this);
   
}

   int lastX;//用於保存上一次事件的座標。
   int
lastY;

   
//v----ImageView對象
   
@Override
   
public boolean onTouch(View v, MotionEvent event) {
       //任何事件都會觸發這裏。包括按下、移動
       
int eventX = (int) event.getRawX();
       int
eventY = (int) event.getRawY();
       switch
(event.getAction()) {
           case MotionEvent.ACTION_DOWN:
               //按下執行這裏,按下移動,這裏只執行一次。獲取剛剛按下位置座標
               
lastX = eventX;
               
lastY = eventY;
               break;
           case
MotionEvent.ACTION_MOVE:
               //先獲取偏移距離:此時的eventX與上邊的eventX不是一個值
               
int dx = eventX - lastX;
               int
dy = eventY - lastY;


               
//計算控件最新座標
               
int left = mImageView.getLeft() + dx;
               int
top = mImageView.getTop() + dy;
               int
right = mImageView.getRight() + dx;
               int
bottom = mImageView.getBottom() + dy;

               
//重新設置控件在父組件中的位置。參數是當前控件的四個座標值
               
mImageView.layout(left, top, right, bottom);

               
//最後重新給lastXlastY賦值。記錄最後一次的值
               
lastX = eventX;
               
lastY = eventY;
               break;

           default
:
               break;
       
}
       //表示我(圖片控件),消費事件
       
return true;
   
}
}

運行程序結果如下:


上面圖片完成了基本拖動功能,但是還是存在問題的。我們不希望它拖出屏幕,那麼邏輯就需要做如下修改:

拖動到屏幕左右上下位置時候,控制不越界。

public class MainActivity extends AppCompatActivity implements View.OnTouchListener {

   private ImageView mImageView;
   private
RelativeLayout mParentView;
   private int
mParentRight;
   private int
mParentBottom;

   
@Override
   
protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       
setContentView(R.layout.activity_main);
       
mImageView = (ImageView) findViewById(R.id.iv_main);
       
//獲取控件父親組件的實例
       
mParentView = (RelativeLayout) mImageView.getParent();
       
mImageView.setOnTouchListener(this);
   
}

   //兩個變量,用於存儲上一次事件的座標
   
int lastX;
   int
lastY;

   
//v----ImageView對象
   
@Override
   
public boolean onTouch(View v, MotionEvent event) {
       //任何事件都會觸發這裏。包括按下、移動
       
int eventX = (int) event.getRawX();
       int
eventY = (int) event.getRawY();
       switch
(event.getAction()) {
           case MotionEvent.ACTION_DOWN:

               if(mParentBottom == 0){
                   //onCreate方法中獲取到的座標值是00。這是由於繪圖生命週期的原因。onDraw等方法
                   
mParentRight = mParentView.getRight();
                   
mParentBottom = mParentView.getBottom();
               
}


               //按下執行這裏,按下移動,這裏只執行一次。獲取剛剛按下位置座標
               
lastX = eventX;
               
lastY = eventY;

           case
MotionEvent.ACTION_MOVE:
               //先獲取偏移距離:此時的eventX與上邊的eventX不是一個值
               
int dx = eventX - lastX;
               int
dy = eventY - lastY;


               
//計算控件最新座標
               
int left = mImageView.getLeft() + dx;
               int
top = mImageView.getTop() + dy;
               int
right = mImageView.getRight() + dx;
               int
bottom = mImageView.getBottom() + dy;

               
//限制座標
               
if (left < 0) {
                   //控件右邊座標也要設置,否則會讓圖片越變越小
                   
right += -left;
                   
left = 0;
               
}

               if(top<0){
                   //控件底部座標也要設置,否則會讓圖片越變越小
                   
bottom += -top;
                   
top = 0;
               
}

               if(bottom > mParentBottom){
                   top -= (bottom - mParentBottom);
                   
bottom = mParentBottom;
               
}

               if(right > mParentRight){
                   left -= (right - mParentRight);
                   
right = mParentRight;
               
}

               //重新設置控件在父組件中的位置。參數是當前控件的四個座標值
               
mImageView.layout(left, top, right, bottom);

               
//最後重新給lastXlastY賦值。記錄最後一次的值
               
lastX = eventX;
               
lastY = eventY;
               break;

           default
:
               break;
       
}
       //表示我(圖片控件),消費事件。所有的MotionEvent交給我自己處理
       
return true;
   
}
}

通過mParentView = (RelativeLayout) mImageView.getParent();得到父組件控件的實例。在MotionEvent.ACTION_DOWN:按下的時候,拿到服務組件的座標;注意在onCreate方法中獲取到的座標值是[0,0],這是由於繪圖機制以及生命週期有關,還沒有在屏幕上繪製完畢的原因。但是當我們進行事件點擊的時候,肯定全部繪製完畢了。通過如下代碼,控制不超出屏幕:

//限制座標
if (left < 0) {
   //控件右邊座標也要設置,否則會讓圖片越變越小
   
right += -left;
   
left = 0;
}

if(top<0){
   //控件底部座標也要設置,否則會讓圖片越變越小
   
bottom += -top;
   
top = 0;
}

if(bottom > mParentBottom){
   top -= (bottom - mParentBottom);
   
bottom = mParentBottom;
}

if(right > mParentRight){
   left -= (right - mParentRight);
   
right = mParentRight;
}

現在再一次運行程序:


我們發現,這時候拖動的控件是不會超出屏幕的。



喜歡我的朋友可以關注我博客,有問題大家一起交流。也可以動手微信掃描下方二維碼查看更多安卓文章:


打開微信搜索公衆號  Android程序員開發指南  或者手機掃描下方二維碼 在公衆號閱讀更多Android文章。

微信公衆號圖片:







發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章