码迷,mamicode.com
首页 > 其他好文 > 详细

滑动返回

时间:2015-05-22 22:40:19      阅读:159      评论:0      收藏:0      [点我收藏+]

标签:slideoverlaylayout   swip back   

滑动返回

手机屏幕越来越大,单手操作时,无法点击到左上角的回退按钮。看到很多人都有实现这个功能,但是实现的功能过于强大。所以自己写了一个Layout来实现这个功能。整个Layout实现滑动返回只有180行代码。

实现思想

现在有一个ViewGroup和一个View,在这个ViewGroup和View之间加上一个层Overlay,实现滑动时,Overlay和view像→滑动,ViewGroup不动。

比如,Activity的decorView就是ViewGroup,view就是ActionBarOverlayLayout(decorView.getChildAtIndex(0));

将activty的windowbackground职位null,并将windowbackroundcolor置为透明色即可。

源码


public class SlideOverlayLayout extends FrameLayout {

	private onSlideListener mOnSlideListener;

	private int mTouchSlop;
	private Scroller mScroller;

	private float mLastPositionX;
	private float mLastPositonY;

	private boolean mIsSliding;
	private boolean mIsFinish;

	private View mSlidView;

	public SlideOverlayLayout(Context context) {
		super(context);
		init(context);
	}

	public SlideOverlayLayout(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	public SlideOverlayLayout(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init(context);
	}

	private void init(Context context) {
		mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
		mScroller = new Scroller(context);
	}

	public void setOnSlideListener(onSlideListener onSlideListener) {
		mOnSlideListener = onSlideListener;
	}

	public void slide() {
		if (mOnSlideListener == null) {
			mSlidView = null;
			return;
		}

		mOnSlideListener.insertSlideOverlayLayout(this);

		if (getChildCount() == 0) {
			throw new IllegalArgumentException(
					"slide view at least have one child, which is the slid view.");
		}

		mSlidView = getChildAt(getChildCount() - 1);
	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent event) {
		if (mOnSlideListener == null) {
			return super.onInterceptTouchEvent(event);
		}

		if (!mOnSlideListener.canSlide(this, event.getRawX(), event.getRawY())) {
			return super.onInterceptTouchEvent(event);
		}

		switch (event.getAction()) {

		case MotionEvent.ACTION_DOWN:
			mIsSliding = true;
			mLastPositionX = event.getRawX();
			mLastPositonY = event.getRawY();
			break;
		case MotionEvent.ACTION_MOVE:
			float positionX = event.getRawX();
			float positionY = event.getRawY();

			float deltaX = positionX - mLastPositionX;
			float deltaY = positionY - mLastPositonY;

			if (Math.abs(deltaY) < mTouchSlop && deltaX > 0) {
				mLastPositionX = positionX;
				mLastPositonY = positionY;
				return mIsSliding = true;
			} else {
				mIsSliding = false;
			}
			break;
		default:
			break;
		}
		return super.onInterceptTouchEvent(event);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		if (mOnSlideListener == null || !mIsSliding) {
			return super.onTouchEvent(event);
		}

		switch (event.getAction()) {
		case MotionEvent.ACTION_MOVE:
			float positionX = event.getRawX();
			float positionY = event.getRawY();

			float deltaX = positionX - mLastPositionX;

			mLastPositionX = positionX;
			mLastPositonY = positionY;

			if (mSlidView.getScrollX() - deltaX > 0) {
				deltaX = mSlidView.getScrollX();
			}

			mSlidView.scrollBy((int) -deltaX, 0);

			mOnSlideListener.onSlide(this, deltaX - mSlidView.getScrollX());
			break;
		case MotionEvent.ACTION_UP:
			mIsSliding = false;
			int dx;
			if (mIsFinish = mOnSlideListener.canFinish(this,
					-mSlidView.getScrollX())) {
				dx = -(getWidth() + mSlidView.getScrollX()) + 1;
			} else {
				dx = -mSlidView.getScrollX();
			}

			mScroller.startScroll(mSlidView.getScrollX(), 0, dx, 0,
					Math.abs(dx));
			postInvalidate();
			break;
		}
		return true;
	}

	@Override
	public void computeScroll() {
		if (mScroller.computeScrollOffset()) {
			mSlidView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY());
			mOnSlideListener.onSlide(this, - mScroller.getCurrX());
			postInvalidate();
		} else if (mIsFinish) {
			mOnSlideListener.onFinish(this);
		}
	}

	public interface onSlideListener {

		// Insert the slide layout between the container and slid view.
		// Also you can add other views into the layout to let the slid look
		// better.
		// But be sure that the slid view will be the last child to be added in.
		void insertSlideOverlayLayout(SlideOverlayLayout layout);

		// When touching the screen, this will be called with the position where
		// your finger touches.
		boolean canSlide(SlideOverlayLayout layout, float positionX,
				float positionY);

		// This will be called when ever your finger moves with the offset.
		void onSlide(SlideOverlayLayout layout, float offset);

		// When leaving your finger from the screen, this method will be called
		// with the final offset, and return the boolean value which can finish
		// the slid action.
		boolean canFinish(SlideOverlayLayout layout, float offset);

		// when return true by canFinish() method, this will be immediately
		// called when the slide animation overs.
		void onFinish(SlideOverlayLayout layout);
	}
}
如何使用

1.将activity的window置为透明(查看values下的style文件)


 <style name="AppTheme.Translucent"> 
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:colorBackgroundCacheHint">@null</item>
        <item name="android:windowIsTranslucent">true</item>
        <!-- Note that we use the base animation style here (that is no
             animations) because we really have no idea how this kind of
             activity will be used. -->
        <item name="android:windowAnimationStyle">@android:style/Animation</item>
    </style>
2.将其应用到AndroidManifest文件的制定Activity上

        <activity
      		android:name="com.demo.slide.activity.SlideActivity"
            android:theme="@style/AppTheme.Translucent" />
3.在activity中使用SlideOverlayLayout


public class SlideActivity extends Activity implements onSlideListener {

//	private View vSlideAlphaView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		setContentView(R.layout.activity_slide);

		SlideOverlayLayout slideView = new SlideOverlayLayout(this);
		slideView.setOnSlideListener(this);
		slideView.slide();
	}

	@Override
	public void insertSlideOverlayLayout(SlideOverlayLayout layout) {
		ViewGroup root = (ViewGroup) getWindow().getDecorView();

		View contentView = root.getChildAt(0);

		root.removeView(contentView);

//		vSlideAlphaView = new View(this);
//		vSlideAlphaView.setBackgroundColor(Color.BLACK);
//		vSlideAlphaView.getBackground().setAlpha(255 / 2);
//		layout.addView(vSlideAlphaView);

		layout.addView(contentView);
		root.addView(layout);
	}

	@Override
	public void onSlide(SlideOverlayLayout layout, float offset) {
//		float alpha = 0.5f - offset / vSlideAlphaView.getWidth();
//
//		if (alpha < 0) {
//			alpha = 0;
//		}
//
//		vSlideAlphaView.getBackground().setAlpha((int) (255 * alpha));
	}

	@Override
	public boolean canFinish(SlideOverlayLayout layout, float offset) {
		return offset > layout.getWidth() / 3.0f;
	}

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

	@Override
	public boolean canSlide(SlideOverlayLayout layout, float positionX,
			float positonY) {
		return true;
	}

}

注:对这个listener方法的说明

// Insert the slide layout between the container and slid view.
		// Also you can add other views into the layout to let the slid look
		// better.
		// But be sure that the slid view will be the last child to be added in.
		void insertSlideOverlayLayout(SlideOverlayLayout layout);

		// When touching the screen, this will be called with the position where
		// your finger touches.
		boolean canSlide(SlideOverlayLayout layout, float positionX,
				float positionY);

		// This will be called when ever your finger moves with the offset.
		void onSlide(SlideOverlayLayout layout, float offset);

		// When leaving your finger from the screen, this method will be called
		// with the final offset, and return the boolean value which can finish
		// the slid action.
		boolean canFinish(SlideOverlayLayout layout, float offset);

		// when return true by canFinish() method, this will be immediately
		// called when the slide animation overs.
		void onFinish(SlideOverlayLayout layout);

源码地址

SlideDemo


滑动返回

标签:slideoverlaylayout   swip back   

原文地址:http://blog.csdn.net/userqiaohaibin/article/details/45920269

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!