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

来源:互联网 发布:ubuntu启动程序命令 编辑:程序博客网 时间:2024/05/22 05:16

之前就有写过这种小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文章。

微信公众号图片:







0 0
原创粉丝点击