之前有看过xiaanming写的侧滑返回,于是仿照他的Demo,写了这个从上往下滑动或者从下往上滑动结束Activity
先附图一张,由于这台电脑分辨率有问题以及模拟器的缘故,先凑活看吧
先贴代码:
从上往下滑动:
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();
}
}
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();
}
});
}
}
要实现其实很简单,在onTouchEvent里判断手指移动的距离,如果大于自己设定的临界值,则滚动到顶部或者底部,否则回到初始位置。所以这里用到了Scroller,scroller.startScroll后,postInvalidate刷新界面。
最后重写computeScroll,在computeScroll里判断Scroller是否已经finish以及手指移动的距离是否大于自己设定的临界值。
最后一定要记得,在AndroidManifest.xml里要将Activity的Theme设置为Theme.Translucent,否则看不到效果
Demo:http://download.csdn.net/detail/qq_18612815/9615890