Android跟随手指移动
这个杀手不太累 人气:0对View的移动,实现的方法有好几种,原理是通过改变View的位置来移动View,下面来实现这样的效果
- 动画的方法
通过改变View的tranlationX和tranlationY的值来实现移动,首先来写一个自定义View类,重写onTouchEvent方法,实现构造方法
public class MyView extends View { public MyView(Context context) { super(context); } public MyView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } @Override public boolean onTouchEvent(MotionEvent event) { return true;//这里我们要消费这个事件,所以返回了true } }
关于移动的处理逻辑都在onTouchEvent方法中,下面的代码主要针对onTouchEvent方法修改,其它代码不再贴上了
首先要获取手指点击移动在屏幕上的坐标,使用
int x = (int)event.getRawX();//获取x轴上的位置 int y = (int)event.getRawY();//获取y轴上的位置
处理事件的模板代码
switch(event.getAction()){ case MotionEvent.ACTION_DOWN://点击事件 break; case MotionEvent.ACTION_MOVE://移动事件 break; case MotionEvent.ACTION_UP://离开事件 break; default: break; }
通过判断事件的类型,将在ACTION_MOVE事件中计算移动前后的差值来设置View的translationX和translationY值来改变View的位置,这里需要记录上次的位置,所以需要2个变量,代码如下
private int mLaxtX; private int mLaxtY; @Override public boolean onTouchEvent(MotionEvent event) { int x = (int) event.getRawX(); int y = (int) event.getRawY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: break; case MotionEvent.ACTION_MOVE: int deltaX = x - mLastX;//计算x坐标上的差值 int deltaY = y - mLastY;//计算y坐标上的差值 float tranX = getTranslationX() + deltaX ;//要平移的x值 float tranY = getTranslationY() + deltaY;//要平移的y值 setTranslationX(tranX);//设置值 setTranslationY(tranY); break; case MotionEvent.ACTION_UP: break; default: break; } mLastX = x;//记录上次的坐标 mLastY = y; return true; }
- layout方法
View在绘制的时候,会调用onLayout方法来设置显示的位置,可以通过这个方法来实现移动
//layout方法实现 switch (event.getAction()) { case MotionEvent.ACTION_DOWN: break; case MotionEvent.ACTION_MOVE: //计算偏移量 int offsetX = x - mLastX; int offsetY = y - mLastY; //重新布局 layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY); //也可以使用下面这种方法 // offsetLeftAndRight(offsetX); // offsetTopAndBottom(offsetY); break; case MotionEvent.ACTION_UP: break; default: break; } mLastX = x; mLastY = y;
- LayoutParams
LayoutParams保存了一个View的布局参数,通过改变这个参数,重绘View也可以实现移动
//LayoutParams方法 switch (event.getAction()) { case MotionEvent.ACTION_DOWN: break; case MotionEvent.ACTION_MOVE: int offsetX = x - mLastX; int offsetY = y - mLastY; //示例代码的父View是LinearLayout LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams(); layoutParams.leftMargin = getLeft() + offsetX; layoutParams.topMargin = getTop() + offsetY; //下面这两句都可以使用,setLayoutParams也会调用requestLayout // setLayoutParams(layoutParams); requestLayout(); break; case MotionEvent.ACTION_UP: break; default: break; }
这里先介绍这几种方法
完整代码如下:
public class MyView extends View { public MyView(Context context) { super(context); } public MyView(Context context, @Nullable AttributeSet attrs) { super(context, attrs); } public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP) public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { super(context, attrs, defStyleAttr, defStyleRes); } private int mLastX; private int mLastY; @Override public boolean onTouchEvent(MotionEvent event) { int x = (int) event.getRawX(); int y = (int) event.getRawY(); //动画实现移动代码 //-------------------------------------------------- // switch (event.getAction()) { // case MotionEvent.ACTION_DOWN: // // break; // case MotionEvent.ACTION_MOVE: // int delaltax = x - mLastX; // int delaltaY = y - mLastY; // float tranX = getTranslationX() + delaltax; // float tranY = getTranslationY() + delaltaY; // setTranslationX(tranX); // setTranslationY(tranY); // break; // case MotionEvent.ACTION_UP: // // break; // default: // break; // } //----------------------------------------------- //layout方法实现 // switch (event.getAction()) { // case MotionEvent.ACTION_DOWN: // break; // case MotionEvent.ACTION_MOVE: // //计算偏移量 // int offsetX = x - mLastX; // int offsetY = y - mLastY; // //重新布局 // layout(getLeft() + offsetX, getTop() + offsetY, // getRight() + offsetX, getBottom() + offsetY); // //也可以使用下面这种方法 offsetLeftAndRight(offsetX); offsetTopAndBottom(offsetY); // break; // case MotionEvent.ACTION_UP: // break; // default: // break; // } //--------------------------------------------- //LayoutParams方法 switch (event.getAction()) { case MotionEvent.ACTION_DOWN: break; case MotionEvent.ACTION_MOVE: int offsetX = x - mLastX; int offsetY = y - mLastY; //示例代码的父View是LinearLayout LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) getLayoutParams(); layoutParams.leftMargin = getLeft() + offsetX; layoutParams.topMargin = getTop() + offsetY; //下面这两句都可以使用,setLayoutParams也会调用requestLayout // setLayoutParams(layoutParams); requestLayout(); break; case MotionEvent.ACTION_UP: break; default: break; } mLastX = x; mLastY = y; return true; } }
加载全部内容