View的自由拖动(属性动画的实践之一)
来源:互联网 发布:时时彩软件urssc 编辑:程序博客网 时间:2024/06/04 18:03
iPhone 有一个 AssistiveTouch ,就是桌面上那个小圆点,用户可以随意拖动它,虽然最后它也会自动挪到最近的边界上,但是如何实现 View 的任意拖动并最后停在那个位置呢,首先要先弄清楚几个方法。
View :
getTop():顶边相对于父控件顶边的距离。
getBottom():底边相对于父控件顶边的距离。
getLeft():左边相对于父控件左边的距离。
getRight():右边相对于父控件左边的距离。
getX():该控件在 X 轴的坐标,初始值同 getLeft()。
getY():该控件在 Y 轴的坐标,初始值同 getTop()。
getTranslationX():重新设置 X 轴坐标后相对于原坐标的偏移量。
getTranslationY():重新设置 Y 轴坐标后相对于原坐标的偏移量。
MotionEvent:
getX():相对于响应 Touch 事件的控件左边的距离。
getY():相对于响应 Touch 事件的控件顶边的距离。
getRawX():相对于屏幕的顶边的距离。
getRawY():相对于屏幕的左边的距离。
可参照下图来理解。
弄清楚这几个方法,之前我有记录了属性动画的作用和基本使用,而且知道它不单纯是改变视觉效果,还改变了对象的属性,所以我们通过属性动画来实现控件的任意拖动。其实很简单。
通过这张图,我们就可以知道只要算出来 distanceX 和 distanceY ,然后利用属性动画修改控件的 x 、 y ,在原来的 x 、 y 的基础上加上或减去这个 distance 就行了。以 ImageView 为例。
端午节要到了,就在相对布局中放一个萌萌的小粽子:
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/rl_container" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.qinshou.iconmovedemo.MainActivity"> <ImageView android:id="@+id/iv_move" android:layout_width="50dp" android:layout_height="50dp" android:layout_centerInParent="true" android:scaleType="fitXY" android:src="@mipmap/zongzi" /></RelativeLayout>
MainActivity:
public class MainActivity extends AppCompatActivity { private ImageView ivMove; private int containerWidth, containerHeight; //容器宽高 private float lastX, lastY; //最后一次触摸事件的坐标 private RelativeLayout rlContainer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); rlContainer = (RelativeLayout) findViewById(R.id.rl_container); rlContainer.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { //不能直接在onCreate()方法中得到宽高,会得到0,所以注册视图树的观察者来得到宽高 //OnPreDrawListener是当一个视图树将要绘制时,所要调用的回调函数的接口类 containerWidth = rlContainer.getWidth(); containerHeight = rlContainer.getHeight(); return true; } }); ivMove = (ImageView) findViewById(R.id.iv_move); ivMove.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { switch (motionEvent.getAction()) { case MotionEvent.ACTION_DOWN: //记录触摸时的坐标,这里为什么要用getRawX()和getRawY()相信理解getX(),getY()和getRawX(),getRawY()的区别就知道为什么了 lastX = motionEvent.getRawX(); lastY = motionEvent.getRawY(); //return true对事件进行拦截,不继续下发,防止继续响应onClick事件. return true; case MotionEvent.ACTION_MOVE: //每次移动的距离 float distanceX = motionEvent.getRawX() - lastX; float distanceY = motionEvent.getRawY() - lastY; //控件将要移动到的位置,先计算一下,不在ofFloat()方法中再计算是因为要防止控件移动到容器之外. float nextX = ivMove.getX() + distanceX; float nextY = ivMove.getY() + distanceY; //如果将要移动到的 x 轴坐标小于0,则等于0,防止移出容器左边 if (nextX < 0) nextX = 0; //防止移出容器右边 if (nextX > containerWidth - ivMove.getWidth()) nextX = containerWidth - ivMove.getWidth(); //防止移出容器顶边 if (nextY < 0) nextY = 0; //防止移出容器底边 if (nextY > containerHeight - ivMove.getHeight()) nextY = containerHeight - ivMove.getHeight(); //利用属性动画改变控件的x,y坐标 ObjectAnimator mObjectAnimatorX = ObjectAnimator.ofFloat(ivMove, "x", ivMove.getX(), nextX); ObjectAnimator mObjectAnimatorY = ObjectAnimator.ofFloat(ivMove, "y", ivMove.getY(), nextY); AnimatorSet mAnimatorSet = new AnimatorSet(); mAnimatorSet.playTogether(mObjectAnimatorX, mObjectAnimatorY); mAnimatorSet.setDuration(0); mAnimatorSet.start(); //移动完之后记录当前坐标 lastX = motionEvent.getRawX(); lastY = motionEvent.getRawY(); break; } return false; } }); }}
运行程序,可以看到随意拖动控件的效果就实现了,换成 TextView 、 Button 也是一样的。
上面还提到了 getTranslationX() 、和 getTranslationY() 方法,它得到的值是相对于初始 x 、 y 坐标的偏移量而不是上一次,getX() = getLeft() + getTranslationX() , getY() = getTop() + getTranslationY() ,有兴趣的朋友可以自行打印看看。
就这么简单,注释写得很详细了,这只是使用属性动画的一次小实验,这个功能强大的东西还有更多好玩的东西等我探究,希望自己还能爬得更高。
Demo下载
- View的自由拖动(属性动画的实践之一)
- 可在全屏幕自由拖动的view
- 可在全屏幕自由拖动的view
- 实现可自由拖动的view
- Android 可在全屏幕自由拖动的view
- Android可在全屏幕自由拖动的view
- android开发自定义View,可以自由拖动的控件
- 自由拖动的控件
- 控件的自由拖动代码
- 自由拖动的div层
- 实现自定义view(1):可在全屏幕自由拖动的view
- 一直在寻找的,可在全屏幕自由拖动的view,很炫!
- 各个浏览器中鼠标位置的属性 offsetX layerX PageX clientX (自由拖动框,防止文字选中)
- Android View的拖动
- 可以拖动的 view
- Android下拖动任意View代码(使用属性动画,眼前一亮)
- Android用属性动画拖动view到任意位置
- VB自由拖动控件的代码
- maven打包出现错误: Failed to clean project: Failed to delete
- JsonUtil.fromJson -- error
- Java基础
- selenium+java如何进行Q三方登录(续坑)
- javascript,jQuery自执行函数(匿名函数)为什么要把windows, jQuery, undefined作为参数传进去
- View的自由拖动(属性动画的实践之一)
- VT100控制码进行终端扩展显示
- Window环境下mysql读写分离以及主从配置(不错可以的)
- 第二讲 Controller配置汇总
- qml之qmldir文件的使用
- struts2 参数接收不到的原因
- 关于反爬虫,看这一篇就够了
- 信用有多重要?欠款200元,多付4万利息!(附逾期补救办法)
- Struts2 转发和重定向的实现方法