實作滑動的六種方式
- 效果視頻
- 剖析Android坐標系
- 六種方式
- layout
- scrollBy
- offsetLeftAndRight offsetTopAndButton
- LayoutParams
- Scroller
- 平移影片
- 效果視頻
效果視頻
剖析Android坐標系
滑動的本質是移動,滑動的原理就是通過不斷的改變View的坐標而實作,

Android系統提供了很多方法獲取坐標值,可以將其分為兩種類別,具體如下:
View 提供的獲取坐標的方法
getTop():獲取到的是View自身的頂邊到其父布局頂邊的距離
getLeft():獲取到的是View自身的左邊到其父布局左邊的距離
getRight():獲取到的是View自身的右邊到其父布局左邊的距離
getBottom():獲取到的是View自身的底邊到其父布局頂邊的距離
MotionEvent 提供的方法
getX():獲取點擊事件距離控制元件左邊的距離,即視圖坐標
getY():獲取點擊事件距離控制元件頂邊的距離,即視圖坐標
getRawX():獲取點擊事件距離整個螢屏左邊的距離,即絕對坐標
getRawY():獲取點擊事件距離整個螢屏頂邊的距離,即絕對坐標
六種方式
layout
使用絕對坐標系,每次執行移動邏輯后需要重新設定初始化坐標
@Override
public boolean onTouchEvent(MotionEvent event) {
int rawX = (int) (event.getRawX());
int rawY = (int) (event.getRawY());
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
lastX = rawX;
lastY = rawY;
break;
case MotionEvent.ACTION_MOVE:
int offsetX = rawX - lastX;
int offsetY = rawY - lastY;
layout( getLeft()+offsetX,getTop()+offsetY,getRight()+offsetX,getBottom()+offsetY );
lastX = rawX;
lastY = rawY;
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
scrollBy
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
lastX = x;
lastY = y;
break;
case MotionEvent.ACTION_MOVE:
int offsetX = x - lastX;
int offsetY = y - lastY;
((View) getParent()).scrollBy( -offsetX, -offsetY );
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
offsetLeftAndRight offsetTopAndButton
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
lastX = x;
lastY = y;
break;
case MotionEvent.ACTION_MOVE:
int offsetX = x - lastX;
int offsetY = y - lastY;
offsetLeftAndRight( offsetX );
offsetTopAndBottom( offsetY );
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
LayoutParams
通過getLayoutParams()獲取LayoutParams時,需要根據不同的父型別使用設定不同的型別,比如父布局為LinearLayout則設定型別為 LinearLayout.LayoutParams
@Override
public boolean onTouchEvent(MotionEvent event) {
int x = (int) event.getX();
int y = (int) event.getY();
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
lastX = x;
lastY = y;
break;
case MotionEvent.ACTION_MOVE:
int offsetX = x - lastX;
int offsetY = y - lastY;
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams)getLayoutParams();
layoutParams.leftMargin = getLeft()+offsetX;
layoutParams.topMargin = getTop()+offsetY;
setLayoutParams( layoutParams );
break;
case MotionEvent.ACTION_UP:
break;
}
return true;
}
更方便的是直接使用ViewGroup,不需要判斷父布局型別
ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams)getLayoutParams();
layoutParams.leftMargin = getLeft()+offsetX;
layoutParams.topMargin = getTop()+offsetY;
setLayoutParams( layoutParams );
Scroller
初始化Scroller
scroller = new Scroller( context );
重寫computeScroll()方法
使用computeScrollOffset()判定是否完成了整個滑動
@Override
public void computeScroll() {
if (scroller.computeScrollOffset()) {
((View) getParent()).scrollTo( scroller.getCurrX(), scroller.getCurrY() );
invalidate();
}
super.computeScroll();
}
@Override
public boolean onTouchEvent(MotionEvent mv) {
View parent = (View) getParent();
switch (mv.getAction()) {
case MotionEvent.ACTION_DOWN:
lastX = (int) mv.getX();
lastY = (int) mv.getY();
break;
case MotionEvent.ACTION_MOVE:
int upX = (int) (mv.getX() - lastX);
int upY = (int) (mv.getY() - lastY);
parent.scrollBy( -upX, -upY );
break;
case MotionEvent.ACTION_UP:
scroller.startScroll( parent.getScrollX(), parent.getScrollY(), -parent.getScrollX(), -parent.getScrollY(), 1000 );
invalidate();
break;
}
return super.onTouchEvent( mv );
}
平移影片
效果視頻
private void InitAnimation(){
animation = new TranslateAnimation( 0,200,0,200 );
animation.setDuration( 1000 );
}
moveButton.startAnimation( animation );
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/353449.html
標籤:其他
