userqiaohaibin的专栏

滑动返回

手机屏幕越来越大,单手操作时,无法点击到左上角的回退按钮。看到很多人都有实现这个功能,但是实现的功能过于强大。所以自己写了一个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);}@Overridepublic 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);}@Overridepublic 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;}@Overridepublic 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 noanimations) because we really have no idea how this kind ofactivity will be used. –><item name="android:windowAnimationStyle">@android:style/Animation</item></style>2.将其应用到AndroidManifest文件的制定Activity上

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

生命不是一场赛跑,而是一次旅行。比赛在乎终点,而旅行在乎沿途风景。

userqiaohaibin的专栏

相关文章:

你感兴趣的文章:

标签云: