您的位置:首页 > 移动开发 > Android开发

Android滑动返回-swipebacklayout解析

2015-09-24 11:35 656 查看

交互效果



背景

ios7发布时有滑动返回手势操作,产品经理看到后很兴奋,立即要求android增加相同手势操作。由于android系统特性,并不支持两个activity的滑动操作。经过一番研究和挣扎,终于实现了效果。实现原理基本和下文要分析的swipebacklayout类似,我们直接来分析swipebacklayout。

使用方法

使用方法很简单,activity继承SwipeBackActivity就可以了。

实现原理

假设场景

有两个activity – A 和 B,B在A上层 ,手指滑动B返回到A。

实现原理

手指移动B页面的view,因为B被设置为透明,所以会看到A。

分析

swipebacklayout布局对比

使用swipebacklayout的activity



普通activity布局



可以看到,使用了swipebacklayout的activity会在DecorView中增加一层SwipeBackLayout(FrameLayout)。视图跟随手指滑动就是通过SwipeBackLayout来实现的。我们结合代码来看。

布局增加SwipeBackLayout(FrameLayout)

SwipeBackActivity

@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mHelper.onPostCreate();
}


SwipeBackActivityHelper

public void onPostCreate() {
// 在DecorView下增加SwipeBackLayout(FragmentLayout)
mSwipeBackLayout.attachToActivity(mActivity);
}


SwipeBackLayout

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();

// 在DecorView下增加SwipeBackLayout(FragmentLayout)
ViewGroup decor = (ViewGroup) activity.getWindow().getDecorView();
// 拿到第一个子view-decorChild
ViewGroup decorChild = (ViewGroup) decor.getChildAt(0);
decorChild.setBackgroundResource(background);
// 删除子view-decorChild
decor.removeView(decorChild);
// 把子view-decorChild添加到SwipeBackLayout(FragmentLayout)下
addView(decorChild);
setContentView(decorChild);
// 把SwipeBackLayout(FragmentLayout)添加到DecorView下
decor.addView(this);
}


手指滑动,移动页面

SwipeBackLayout

@Override
public boolean onTouchEvent(MotionEvent event) {
// 是否支持手势返回
if (!mEnable) {
return false;
}
// 处理屏幕事件
mDragHelper.processTouchEvent(event);
return true;
}


ViewDragHelper.processTouchEvent(event),我们只分析主要的ACTION_MOVE事件。

case MotionEvent.ACTION_MOVE: {
if (mDragState == STATE_DRAGGING) {
// 计算位置
final int index = MotionEventCompat.findPointerIndex(ev, mActivePointerId);
final float x = MotionEventCompat.getX(ev, index);
final float y = MotionEventCompat.getY(ev, index);
final int idx = (int) (x - mLastMotionX[mActivePointerId]);
final int idy = (int) (y - mLastMotionY[mActivePointerId]);

// 移动view
dragTo(mCapturedView.getLeft() + idx, mCapturedView.getTop() + idy, idx, idy);

saveLastMotion(ev);
} else {
// Check to see if any pointer is now over a draggable view.
// 省略不需要关注的代码
......
}
break;
}


ViewDragHelper.dragTo移动view

private void dragTo(int left, int top, int dx, int dy) {
int clampedX = left;
int clampedY = top;
final int oldLeft = mCapturedView.getLeft();
final int oldTop = mCapturedView.getTop();
// 横向移动-左右
if (dx != 0) {
clampedX = mCallback.clampViewPositionHorizontal(mCapturedView, left, dx);
mCapturedView.offsetLeftAndRight(clampedX - oldLeft);
}
// 纵向移动-上下
if (dy != 0) {
clampedY = mCallback.clampViewPositionVertical(mCapturedView, top, dy);
mCapturedView.offsetTopAndBottom(clampedY - oldTop);
}
// 回调-处理逻辑
if (dx != 0 || dy != 0) {
final int clampedDx = clampedX - oldLeft;
final int clampedDy = clampedY - oldTop;
mCallback
.onViewPositionChanged(mCapturedView, clampedX, clampedY, clampedDx, clampedDy);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android ios7 swipeback