寫這篇文章是因爲看了:http://blog.csdn.net/jdsjlzx/article/details/21231217這篇文章,並下載了demo運行了下。
現對其做了一些修改:
(1) 不在通過setTouchView來處理事件,採用事件攔截機制
(2)加入了右側滑動機制
(3)不在對整個activity的觸摸都有效,採用了觸摸點判斷,使其只是左右邊界時纔有效,從而是activity的觸摸事件和listview等控件的滾動相分開
(4)加入左右滑動切換機制的禁用與開啓功能,使其更方便
本文只貼上部分代碼,不做原理講述,如果你沒有看上一篇:Android 向右滑動銷燬(finish)Activity, 隨着手勢的滑動而滑動的效果(一),請先看一遍。
demo中使用需要注意的地方,在代碼中都有註釋,有任何問題歡迎聯繫。
1、activity佈局,根節點使用定義的view(只對需要滑動的佈局加即可)
<?xml version="1.0" encoding="utf-8"?>
<com.example.view.SildingFinishLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/slidingLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:background="#88ff90" >
<Button
android:id="@+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="單向滑動"
/>
</LinearLayout>
</com.example.view.SildingFinishLayout>
2、SildingFinishLayout的實現
public class SildingFinishLayout extends RelativeLayout{
private final String TAG = SildingFinishLayout.class.getName();
/**
* SildingFinishLayout佈局的父佈局
*/
private ViewGroup mParentView;
/**
* 滑動的最小距離
*/
private int mTouchSlop;
/**
* 按下點的X座標
*/
private int downX;
/**
* 按下點的Y座標
*/
private int downY;
/**
* 臨時存儲X座標
*/
private int tempX;
/**
* 滑動類
*/
private Scroller mScroller;
/**
* SildingFinishLayout的寬度
*/
private int viewWidth;
/**
* 記錄是否正在滑動
*/
private boolean isSilding;
private OnSildingFinishListener onSildingFinishListener;
private boolean enableLeftSildeEvent = true; //是否開啓左側切換事件
private boolean enableRightSildeEvent = true; // 是否開啓右側切換事件
private final int size = 20; //按下時範圍(處於這個範圍內就啓用切換事件,目的是使當用戶從左右邊界點擊時才響應)
private boolean isIntercept = false; //是否攔截觸摸事件
private boolean canSwitch;//是否可切換
private boolean isSwitchFromLeft = false; //左側切換
private boolean isSwitchFromRight = false; //右側側切換
public SildingFinishLayout(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SildingFinishLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
Log.e(TAG, "設備的最小滑動距離:" + mTouchSlop);
mScroller = new Scroller(context);
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
if (changed) {
// 獲取SildingFinishLayout所在佈局的父佈局
mParentView = (ViewGroup) this.getParent();
viewWidth = this.getWidth();
}
Log.e(TAG, "viewWidth=" + viewWidth);
}
public void setEnableLeftSildeEvent(boolean enableLeftSildeEvent) {
this.enableLeftSildeEvent = enableLeftSildeEvent;
}
public void setEnableRightSildeEvent(boolean enableRightSildeEvent) {
this.enableRightSildeEvent = enableRightSildeEvent;
}
/**
* 設置OnSildingFinishListener, 在onSildingFinish()方法中finish Activity
*
* @param onSildingFinishListener
*/
public void setOnSildingFinishListener(
OnSildingFinishListener onSildingFinishListener) {
this.onSildingFinishListener = onSildingFinishListener;
}
//是否攔截事件,如果不攔截事件,對於有滾動的控件的界面將出現問題(相沖突)
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
float downX = ev.getRawX();
Log.e(TAG, "downX =" + downX + ",viewWidth=" + viewWidth);
if(enableLeftSildeEvent && downX < size){
Log.e(TAG, "downX 在左側範圍內 ,攔截事件");
isIntercept = true;
isSwitchFromLeft = true;
isSwitchFromRight = false;
return true;
}else if(enableRightSildeEvent && downX > (viewWidth - size)){
Log.e(TAG, "downX 在右側範圍內 ,攔截事件");
isIntercept = true;
isSwitchFromRight = true;
isSwitchFromLeft = false;
return true;
}else{
Log.e(TAG, "downX 不在範圍內 ,不攔截事件");
isIntercept = false;
isSwitchFromLeft = false;
isSwitchFromRight = false;
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
if(!isIntercept){//不攔截事件時 不處理
return false;
}
switch (event.getAction()){
case MotionEvent.ACTION_DOWN:
downX = tempX = (int) event.getRawX();
downY = (int) event.getRawY();
break;
case MotionEvent.ACTION_MOVE:
int moveX = (int) event.getRawX();
int deltaX = tempX - moveX;
tempX = moveX;
if (Math.abs(moveX - downX) > mTouchSlop && Math.abs((int) event.getRawY() - downY) < mTouchSlop) {
isSilding = true;
}
Log.e(TAG, "scroll deltaX=" + deltaX);
if(enableLeftSildeEvent){//左側滑動
if (moveX - downX >= 0 && isSilding) {
mParentView.scrollBy(deltaX, 0);
}
}
if(enableRightSildeEvent){//右側滑動
if (moveX - downX <= 0 && isSilding) {
mParentView.scrollBy(deltaX, 0);
}
}
Log.e(TAG + "/onTouchEvent", "mParentView.getScrollX()=" + mParentView.getScrollX());
break;
case MotionEvent.ACTION_UP:
isSilding = false;
//mParentView.getScrollX() <= -viewWidth / 2 ==>指左側滑動
//mParentView.getScrollX() >= viewWidth / 2 ==>指右側滑動
if (mParentView.getScrollX() <= -viewWidth / 2 || mParentView.getScrollX() >= viewWidth / 2) {
canSwitch = true;
if(isSwitchFromLeft){
scrollToRight();
}
if(isSwitchFromRight){
scrollToLeft();
}
} else {
scrollOrigin();
canSwitch = false;
}
break;
}
return true;
}
/**
* 滾動出界面至右側
*/
private void scrollToRight() {
final int delta = (viewWidth + mParentView.getScrollX());
// 調用startScroll方法來設置一些滾動的參數,我們在computeScroll()方法中調用scrollTo來滾動item
mScroller.startScroll(mParentView.getScrollX(), 0, -delta + 1, 0, Math.abs(delta));
postInvalidate();
}
/**
* 滾動出界面至左側
*/
private void scrollToLeft() {
final int delta = (viewWidth - mParentView.getScrollX());
// 調用startScroll方法來設置一些滾動的參數,我們在computeScroll()方法中調用scrollTo來滾動item
mScroller.startScroll(mParentView.getScrollX(), 0, delta - 1, 0, Math.abs(delta));//此處就不可用+1,也不卡直接用delta
postInvalidate();
}
/**
* 滾動到起始位置
*/
private void scrollOrigin() {
int delta = mParentView.getScrollX();
mScroller.startScroll(mParentView.getScrollX(), 0, -delta, 0,
Math.abs(delta));
postInvalidate();
}
@Override
public void computeScroll(){
// 調用startScroll的時候scroller.computeScrollOffset()返回true,
if (mScroller.computeScrollOffset()) {
mParentView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
postInvalidate();
if (mScroller.isFinished()) {
if (onSildingFinishListener != null && canSwitch) {
Log.e(TAG, "mScroller finish");
if(isSwitchFromLeft){//回調,左側切換事件
onSildingFinishListener.onSildingBack();
}
if(isSwitchFromRight){//右側切換事件
onSildingFinishListener.onSildingForward();
}
}
}
}
}
public interface OnSildingFinishListener {
public void onSildingBack();
public void onSildingForward();
}
}
3、BaseActivity
/**
* 1. 必須設置透明風格,設置透明後需對Activity設置一個背景色,其遮蓋效果
* 2. 要調用initBaseActivity(boolean enableLeftSilde, boolean enableRigftSilde)
*
* @ enableLeftSilde : 開啓左側
* @ enableRightSilde : 開啓右側
*
* */
public class BaseActivity extends Activity implements OnSildingFinishListener{
private SildingFinishLayout sildingLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
/**
* @enableLeftSilde : 開啓左側
* @enableRightSilde : 開啓右側
* */
public void initBaseActivity(boolean enableLeftSilde, boolean enableRigftSilde){
sildingLayout = (SildingFinishLayout) findViewById(R.id.slidingLayout);
sildingLayout.setOnSildingFinishListener(this);
sildingLayout.setEnableLeftSildeEvent(enableLeftSilde);
sildingLayout.setEnableRightSildeEvent(enableRigftSilde);
}
@Override
public void onSildingBack() {
Toast.makeText(getApplicationContext(), "back", Toast.LENGTH_SHORT).show();
finish();
}
@Override
public void onSildingForward() {
Toast.makeText(getApplicationContext(), "前進", Toast.LENGTH_SHORT).show();
finish();
}
}
歡迎有需要的朋友下載,0積分,有問題相互交流。
下載地址:
Activity滑動跳轉