對(duì)View的移動(dòng),實(shí)現(xiàn)的方法有好幾種督赤,原理是通過改變View的位置來(lái)移動(dòng)View嘁灯,下面來(lái)實(shí)現(xiàn)這樣的效果
- 動(dòng)畫的方法
通過改變View的tranlationX和tranlationY的值來(lái)實(shí)現(xiàn)移動(dòng),首先來(lái)寫一個(gè)自定義View類躲舌,重寫onTouchEvent方法丑婿,實(shí)現(xiàn)構(gòu)造方法
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;//這里我們要消費(fèi)這個(gè)事件,所以返回了true
}
}
關(guān)于移動(dòng)的處理邏輯都在onTouchEvent方法中没卸,下面的代碼主要針對(duì)onTouchEvent方法修改枯冈,其它代碼不再貼上了
首先要獲取手指點(diǎn)擊移動(dòng)在屏幕上的坐標(biāo),使用
int x = (int)event.getRawX();//獲取x軸上的位置
int y = (int)event.getRawY();//獲取y軸上的位置
處理事件的模板代碼
switch(event.getAction()){
case MotionEvent.ACTION_DOWN://點(diǎn)擊事件
break;
case MotionEvent.ACTION_MOVE://移動(dòng)事件
break;
case MotionEvent.ACTION_UP://離開事件
break;
default:
break;
}
通過判斷事件的類型办悟,將在ACTION_MOVE事件中計(jì)算移動(dòng)前后的差值來(lái)設(shè)置View的translationX和translationY值來(lái)改變View的位置尘奏,這里需要記錄上次的位置,所以需要2個(gè)變量病蛉,代碼如下
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;//計(jì)算x坐標(biāo)上的差值
int deltaY = y - mLastY;//計(jì)算y坐標(biāo)上的差值
float tranX = getTranslationX() + deltaX ;//要平移的x值
float tranY = getTranslationY() + deltaY;//要平移的y值
setTranslationX(tranX);//設(shè)置值
setTranslationY(tranY);
break;
case MotionEvent.ACTION_UP:
break;
default:
break;
}
mLastX = x;//記錄上次的坐標(biāo)
mLastY = y;
return true;
}
- layout方法
View在繪制的時(shí)候炫加,會(huì)調(diào)用onLayout方法來(lái)設(shè)置顯示的位置瑰煎,可以通過這個(gè)方法來(lái)實(shí)現(xiàn)移動(dòng)
//layout方法實(shí)現(xiàn)
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE:
//計(jì)算偏移量
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保存了一個(gè)View的布局參數(shù),通過改變這個(gè)參數(shù)俗孝,重繪View也可以實(shí)現(xiàn)移動(dòng)
//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也會(huì)調(diào)用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();
//動(dòng)畫實(shí)現(xiàn)移動(dòng)代碼
//--------------------------------------------------
// 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方法實(shí)現(xiàn)
// switch (event.getAction()) {
// case MotionEvent.ACTION_DOWN:
// break;
// case MotionEvent.ACTION_MOVE:
// //計(jì)算偏移量
// 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也會(huì)調(diào)用requestLayout
// setLayoutParams(layoutParams);
requestLayout();
break;
case MotionEvent.ACTION_UP:
break;
default:
break;
}
mLastX = x;
mLastY = y;
return true;
}
}