您的位置:首页 > 移动开发 > Android开发

Android简易实战教程--第五十二话《满屏拖动的控件2》

2017-01-22 11:50 471 查看
之前就有写过这种小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);

               //最后重新给lastX,lastY赋值。记录最后一次的值
               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方法中获取到的坐标值是0,0。这是由于绘图生命周期的原因。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);

               //最后重新给lastX,lastY赋值。记录最后一次的值
               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文章。微信公众号图片:


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐