package com.example.liujian.lockscreendemo.swipe;
import android.app.Activity;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.Scroller;
/**
* @author xiaanming
* @blog http://blog.csdn.net/xiaanming
*/
public class SwipeUpLayout extends FrameLayout {
private static final String TAG = SwipeUpLayout.class.getSimpleName( );
private static final long MAX_VELOCITY_Y = -4000;
private VelocityTracker mVelocityTracker;
private int mPointerId;
private int mMaxVelocity;
private boolean needFinish = false;
private View mContentView;
private int mTouchSlop;
private int downX;
private int downY;
private int tempX;
private int tempY;
private Scroller mScroller;
private int viewWidth;
private int viewHeight;
private boolean isSilding;
private boolean isFinish;
private Activity mActivity;
private OnSwipeBackListener mListener;
public interface OnSwipeBackListener {
void onFinish( );
}
public void setOnSwipeBackListener( OnSwipeBackListener l ) {
mListener = l;
}
public SwipeUpLayout( Context context, AttributeSet attrs ) {
this( context, attrs, 0 );
}
public SwipeUpLayout( Context context, AttributeSet attrs, int defStyle ) {
super( context, attrs, defStyle );
mTouchSlop = ViewConfiguration.get( context ).getScaledTouchSlop( );
mScroller = new Scroller( context );
mMaxVelocity = ViewConfiguration.get( context ).getMaximumFlingVelocity( );
}
public void attachToActivity( Activity activity ) {
mActivity = activity;
TypedArray a = activity.getTheme( ).obtainStyledAttributes( new int[] { android.R.attr.windowBackground } );
int background = a.getResourceId( 0, 0 );
a.recycle( );
ViewGroup decor = ( ViewGroup ) activity.getWindow( ).getDecorView( );
ViewGroup decorChild = ( ViewGroup ) decor.getChildAt( 0 );
decorChild.setBackgroundResource( background );
decor.removeView( decorChild );
addView( decorChild );
setContentView( decorChild );
decor.addView( this );
}
private void setContentView( View decorChild ) {
mContentView = ( View ) decorChild.getParent( );
}
/**
* 事件拦截操作
*/
@Override
public boolean onInterceptTouchEvent( MotionEvent ev ) {
if( isFinish ) {
return true;
}
switch( ev.getAction( ) ) {
case MotionEvent.ACTION_DOWN:
downY = tempY = ( int ) ev.getRawY( );
downX = ( int ) ev.getRawX( );
break;
case MotionEvent.ACTION_MOVE:
int moveY = ( int ) ev.getRawY( );
// 满足此条件屏蔽SildingFinishLayout里面子类的touch事件
if( moveY - downY > mTouchSlop && Math.abs( ( int ) ev.getRawX( ) - downX ) < mTouchSlop ) {
return true;
}
break;
default:
break;
}
return super.onInterceptTouchEvent( ev );
}
@Override
public boolean onTouchEvent( MotionEvent event ) {
acquireVelocityTracker( event );
switch( event.getAction( ) ) {
case MotionEvent.ACTION_DOWN:
mPointerId = event.getPointerId( 0 );
break;
case MotionEvent.ACTION_MOVE:
touchEvenMove( event );
break;
case MotionEvent.ACTION_UP:
touchEvenUp( );
releaseVelocityTracker( );
break;
default:
break;
}
return true;
}
/**
* @param event 向VelocityTracker添加MotionEvent
* @see VelocityTracker#obtain()
* @see VelocityTracker#addMovement(MotionEvent)
*/
private void acquireVelocityTracker( final MotionEvent event ) {
if( null == mVelocityTracker ) {
mVelocityTracker = VelocityTracker.obtain( );
}
mVelocityTracker.addMovement( event );
}
private void releaseVelocityTracker( ) {
if( null != mVelocityTracker ) {
mVelocityTracker.clear( );
mVelocityTracker.recycle( );
mVelocityTracker = null;
}
}
/**
* 记录当前速度
*
* @param velocityX x轴速度
* @param velocityY y轴速度
*/
private void recodeInfo( final float velocityX, final float velocityY ) {
//向上滑动,去到一定加速度,退出
needFinish = velocityY < MAX_VELOCITY_Y;
}
/**
* 向上滑动
*/
private void touchEvenUp( ) {
isSilding = false;
if( mContentView.getScrollY( ) >= viewHeight / 2 || needFinish ) {
isFinish = true;
scrollUp( );
} else {
scrollOrigin( );
isFinish = false;
}
}
/**
* 向上滑动
*
* @param event
*/
private void touchEvenMove( MotionEvent event ) {
//求伪瞬时速度
mVelocityTracker.computeCurrentVelocity( 1000, mMaxVelocity );
float velocityX = mVelocityTracker.getXVelocity( mPointerId );
float velocityY = mVelocityTracker.getYVelocity( mPointerId );
recodeInfo( velocityX, velocityY );
int moveY = ( int ) event.getRawY( );
int deltaY = tempY - moveY;
tempY = moveY;
if( moveY - downY < mTouchSlop && Math.abs( ( int ) event.getRawX( ) - downX ) < mTouchSlop ) {
isSilding = true;
}
if( moveY - downY <= 0 && isSilding ) {
mContentView.scrollBy( 0, deltaY );
}
}
@Override
protected void onLayout( boolean changed, int l, int t, int r, int b ) {
super.onLayout( changed, l, t, r, b );
if( changed ) {
viewWidth = this.getWidth( );
viewHeight = this.getHeight( );
}
}
/**
* 向上滚动出界面
*/
private void scrollUp( ) {
final int delta = ( viewHeight - mContentView.getScrollY( ) );
mScroller.startScroll( 0, mContentView.getScrollY( ), 0, delta + 1, Math.abs( delta ) );
postInvalidate( );
}
/**
* 从上滚动到起始位置
*/
private void scrollOrigin( ) {
int delta = mContentView.getScrollY( );
mScroller.startScroll( 0, mContentView.getScrollY( ), 0, -delta, Math.abs( delta ) );
postInvalidate( );
}
@Override
public void computeScroll( ) {
// 调用startScroll的时候scroller.computeScrollOffset()返回true,
if( mScroller.computeScrollOffset( ) ) {
mContentView.scrollTo( mScroller.getCurrX( ), mScroller.getCurrY( ) );
postInvalidate( );
if( mScroller.isFinished( ) && isFinish ) {
mActivity.finish( );
if( mListener != null ) {
mListener.onFinish( );
}
}
}
}
public void reset( ) {
isFinish = false;
mScroller.setFinalX( 0 );
mScroller.setFinalY( 0 );
postInvalidate( );
}
}
- 1
- 2
前往页