Android从上往下滑动或从下往上滑动结束Activity

之前有看过xiaanming写的侧滑返回,于是仿照他的Demo,写了这个从上往下滑动或者从下往上滑动结束Activity


先附图一张,由于这台电脑分辨率有问题以及模拟器的缘故,先凑活看吧


Android从上往下滑动或从下往上滑动结束Activity_第1张图片


先贴代码:

从上往下滑动:


import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.Scroller;

/***
 * 
 * 从上向下滑结束Activity
 * 
 * @author 帽檐遮不住阳光
 * 
 */
public class TopToBottomFinishLayout extends RelativeLayout {
	
	/**
	 * TopToBottomFinishLayout布局的父布局
	 */
	private ViewGroup mParentView;
	/**
	 * 滑动的最小距离
	 */
	private int mTouchSlop;
	/**
	 * 按下点的X坐标
	 */
	private int downX;
	/**
	 * 按下点的Y坐标
	 */
	private int downY;
	/**
	 * 临时存储X坐标
	 */
	private int tempY;
	/**
	 * 滑动类
	 */
	private Scroller mScroller;
	/**
	 * TopToBottomFinishLayout的宽度
	 */
	private int viewHeight;

	private boolean isSilding;

	private OnFinishListener onFinishListener;
	private boolean isFinish;

	public TopToBottomFinishLayout(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public TopToBottomFinishLayout(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);

		mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
		mScroller = new Scroller(context);
	}

	/**
	 * 事件拦截操作
	 */
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {

		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN:
			downX = (int) ev.getRawX();
			downY = tempY = (int) ev.getRawY();
			break;
		case MotionEvent.ACTION_MOVE:
			int moveY = (int) ev.getRawY();
			// 满足此条件屏蔽SildingFinishLayout里面子类的touch事件
			if (Math.abs(moveY - downY) > mTouchSlop
					&& Math.abs((int) ev.getRawX() - downX) < mTouchSlop) {
				return true;
			}
			break;
		}
		return super.onInterceptTouchEvent(ev);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_MOVE:
			int moveY = (int) event.getRawY();// 触摸点相对于屏幕的位置
			int deltaY = tempY - moveY;
			tempY = moveY;
			if (Math.abs(moveY - downY) > mTouchSlop
					&& Math.abs((int) event.getRawX() - downX) < mTouchSlop) {
				isSilding = true;
			}

			if (moveY - downY >= 0 && isSilding) {
				mParentView.scrollBy(0, deltaY);
			}
			break;
		case MotionEvent.ACTION_UP:
			isSilding = false;
			if (mParentView.getScrollY() <= -viewHeight / 3) {
				isFinish = true;
				scrollBottom();
			} else {
				scrollOrigin();
				isFinish = false;
			}
			break;
		}

		return true;
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		super.onLayout(changed, l, t, r, b);
		if (changed) {
			mParentView = (ViewGroup) this.getParent();
			viewHeight = this.getHeight();
		}
	}

	/***
	 * 接口回调
	 */
	public void setOnFinishListener(
			OnFinishListener onSildingFinishListener) {
		this.onFinishListener = onSildingFinishListener;
	}

	/**
	 * 滚动出界面
	 */
	private void scrollBottom() {
		final int delta = (viewHeight + mParentView.getScrollY());
		mScroller.startScroll(0, mParentView.getScrollY(), 0, -delta + 1,
				Math.abs(delta));
		postInvalidate();
	}

	/**
	 * 滚动到起始位置
	 */
	private void scrollOrigin() {
		int delta = mParentView.getScrollY();
		mScroller.startScroll(0, mParentView.getScrollY(), 0, -delta,
				Math.abs(delta));
		postInvalidate();
	}

	@Override
	public void computeScroll() {
		if (mScroller.computeScrollOffset()) {
			mParentView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
			postInvalidate();

			if (mScroller.isFinished() && isFinish) {
				if (onFinishListener != null) {
					onFinishListener.onFinish();
				} else {
					// 没有设置OnSildingFinishListener,让其滚动到其实位置
					scrollOrigin();
					isFinish = false;
				}
			}
		}
	}

	public interface OnFinishListener {
		public void onFinish();
	}

}


从下往上滑动:


import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.RelativeLayout;
import android.widget.Scroller;

/***
 * 
 * 从下向上滑结束Activity
 * 
 * @author 帽檐遮不住阳光
 * 
 */
public class BottomToTopFinishLayout extends RelativeLayout {
	
	/**
	 * BottomFinishLayout布局的父布局
	 */
	private ViewGroup mParentView;
	/**
	 * 滑动的最小距离
	 */
	private int mTouchSlop;
	/**
	 * 按下点的X坐标
	 */
	private int downX;
	/**
	 * 按下点的Y坐标
	 */
	private int downY;
	/**
	 * 临时存储X坐标
	 */
	private int tempY;
	/**
	 * 滑动类
	 */
	private Scroller mScroller;
	/**
	 * BottomFinishLayout的宽度
	 */
	private int viewHeight;

	private boolean isSilding;

	private OnFinishListener onFinishListener;
	private boolean isFinish;

	public BottomToTopFinishLayout(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public BottomToTopFinishLayout(Context context, AttributeSet attrs,
			int defStyle) {
		super(context, attrs, defStyle);

		mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
		mScroller = new Scroller(context);
	}

	/**
	 * 事件拦截操作
	 */
	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {

		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN:
			downX = (int) ev.getRawX();
			downY = tempY = (int) ev.getRawY();
			break;
		case MotionEvent.ACTION_MOVE:
			int moveY = (int) ev.getRawY();
			// 满足此条件屏蔽SildingFinishLayout里面子类的touch事件
			if (Math.abs(downY - moveY) > mTouchSlop
					&& Math.abs((int) ev.getRawX() - downX) < mTouchSlop) {
				return true;
			}
			break;
		}
		return super.onInterceptTouchEvent(ev);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		switch (event.getAction()) {
		case MotionEvent.ACTION_MOVE:
			int moveY = (int) event.getRawY();// 触摸点相对于屏幕的位置
			int deltaY = moveY - tempY;
			tempY = moveY;
			if (Math.abs(downY - moveY) > mTouchSlop
					&& Math.abs((int) event.getRawX() - downX) < mTouchSlop) {
				isSilding = true;
			}

			if (downY - moveY >= 0 && isSilding) {
				mParentView.scrollBy(0, -deltaY);
			}
			break;
		case MotionEvent.ACTION_UP:
			isSilding = false;
			System.out.println("vvv===========" + mParentView.getScrollY());
			System.out.println("/3============" + viewHeight / 3);
			if (mParentView.getScrollY() >= viewHeight / 3) {
				isFinish = true;
				scrollTop();
			} else {
				scrollOrigin();
				isFinish = false;
			}
			break;
		}
		return true;
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		super.onLayout(changed, l, t, r, b);
		if (changed) {
			mParentView = (ViewGroup) this.getParent();
			viewHeight = this.getHeight();
		}
	}

	/***
	 * 接口回调
	 */
	public void setOnFinishListener(OnFinishListener onSildingFinishListener) {
		this.onFinishListener = onSildingFinishListener;
	}

	/**
	 * 滚动出界面
	 */
	private void scrollTop() {
		final int delta = (viewHeight - mParentView.getScrollY());
		mScroller.startScroll(0, mParentView.getScrollY(), 0, delta - 1,
				Math.abs(delta));
		postInvalidate();
	}

	/**
	 * 滚动到起始位置
	 */
	private void scrollOrigin() {
		int delta = mParentView.getScrollY();
		mScroller.startScroll(0, mParentView.getScrollY(), 0, -delta,
				Math.abs(delta));
		postInvalidate();
	}

	@Override
	public void computeScroll() {
		if (mScroller.computeScrollOffset()) {
			mParentView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
			postInvalidate();
			if (mScroller.isFinished() && isFinish) {
				if (onFinishListener != null) {
					onFinishListener.onFinish();
				} else {
					// 没有设置OnSildingFinishListener,让其滚动到其实位置
					scrollOrigin();
					isFinish = false;
				}
			}
		}
	}

	public interface OnFinishListener {
		public void onFinish();
	}

}


Activity:

 public class FromTopActivity extends Activity {


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_from_top);
TopToBottomFinishLayout bottomFinishLayout = (TopToBottomFinishLayout) findViewById(R.id.layout);
bottomFinishLayout.setOnFinishListener(new OnFinishListener() {


@Override
public void onFinish() {
finish();
}
});
}


}

layout:




    




要实现其实很简单,在onTouchEvent里判断手指移动的距离,如果大于自己设定的临界值,则滚动到顶部或者底部,否则回到初始位置。所以这里用到了Scroller,scroller.startScroll后,postInvalidate刷新界面。

最后重写computeScroll,在computeScroll里判断Scroller是否已经finish以及手指移动的距离是否大于自己设定的临界值。


最后一定要记得,在AndroidManifest.xml里要将Activity的Theme设置为Theme.Translucent,否则看不到效果


Demo:http://download.csdn.net/detail/qq_18612815/9615890



你可能感兴趣的:(Android从上往下滑动或从下往上滑动结束Activity)