现在有很多App支持右滑返回,比如知乎,效果比较赞。
于是自己对Activity和Fragment进行了继承,派生出SwipeBackActivity和SwipeBackFragment,用于对这种效果的实现,也就是只要继承这两个类就可以了。
效果如下
Fragment
Frgament的效果实现比Activity稍微简单,因为Activity要考虑到dectorView。
支持滑动的控件SwipeLayout,核心思路就是把原有的控件添加到支持滑动的控件中,SwipeLayout要注意计算手势速度,源码如下:
package com.ui.jerry.swipebackdemo; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.VelocityTracker; import android.view.View; import android.view.ViewConfiguration; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.Scroller; import android.widget.Toast; public class SwipeLayout extends LinearLayout { public static final String TAG = "SwipeLayout"; private View mEmptyView; private View mContentView; private int mLeftEdge; private int mWidth; private int mMaxScrollX; private Scroller mScroller; private VelocityTracker mVelocityTracker = null; private int mMaxFlingVelocity; private int mLastX; ViewGroup.LayoutParams childParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); private Context mContext; public static final int DURATION = 1500; //满屏滑动时间 public static final int OPEN_ANIM_DURATION = 1000; public static int SNAP_VELOCITY = 600; //最小的滑动速率 private OnFinishListener mOnFinishListener; public SwipeLayout(Context context) { this(context, null); } public SwipeLayout(Context context, AttributeSet attrs) { super(context, attrs); mContext = context; init(); } public void setOnFinishListener(OnFinishListener mOnFinishListener) { this.mOnFinishListener = mOnFinishListener; } void init() { mScroller = new Scroller(mContext); mMaxFlingVelocity = ViewConfiguration.get(mContext).getScaledMaximumFlingVelocity(); mWidth = DisplayUtils.getScreenWidth(mContext) * 2; mMaxScrollX = mWidth / 2; mLeftEdge = mMaxScrollX - mMaxScrollX / 3; setOrientation(LinearLayout.HORIZONTAL); childParams.width = DisplayUtils.getScreenWidth(mContext); mEmptyView = LayoutInflater.from(mContext).inflate(R.layout.view_translate, null); addView(mEmptyView, childParams); } public void setContentView(View contentView) { if (mContentView != null) { removeView(mContentView); } mContentView = contentView; addView(contentView, childParams); postDelayed(new Runnable() { @Override public void run() { openActivityAnimation(); } }, 200); } /** * 获取速度追踪器 * * @return */ private VelocityTracker getVelocityTracker() { if (mVelocityTracker == null) { mVelocityTracker = VelocityTracker.obtain(); } return mVelocityTracker; } /** * 回收速度追踪器 */ private void recycleVelocityTracker() { if (mVelocityTracker != null) { mVelocityTracker.clear(); mVelocityTracker.recycle(); mVelocityTracker = null; } } @Override public boolean onTouchEvent(MotionEvent ev) { //1.获取速度追踪器 getVelocityTracker(); //2.将当前事件纳入到追踪器中 mVelocityTracker.addMovement(ev); int pointId = -1; switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: //如果屏幕的动画还没结束,你就按下了,我们就结束上一次动画,即开始这次新ACTION_DOWN的动画 // clearScrollHis(); mLastX = (int) ev.getX(); pointId = ev.getPointerId(0); break; case MotionEvent.ACTION_MOVE: int nextScrollX = (int) (mLastX - ev.getX() + getScrollX()); if (scrollTo(nextScrollX)) { mLastX = (int) ev.getX(); } break; case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: //3.计算当前速度 mVelocityTracker.computeCurrentVelocity(1000, mMaxFlingVelocity); //获取x y方向上的速度 float vX = mVelocityTracker.getXVelocity(pointId); Log.i(TAG, "mVelocityX:" + vX); //大于某个速率 直接滑动 if (vX > SNAP_VELOCITY) { scrollToLeft(); } else if (vX < -SNAP_VELOCITY) { scrollToRight(); } else { snapToDestation(); } //4.回收速度追踪器 recycleVelocityTracker(); break; } return true; } private void openActivityAnimation() { clearScrollHis(); mScroller.startScroll(getScrollX(), 0, mMaxScrollX - getScrollX(), 0, OPEN_ANIM_DURATION); invalidate();//这里必须调用invalidate()才能保证computeScroll()会被调用,否则不一定会刷新界面,看不到滚动效果 } public void closeActivityAnimation() { clearScrollHis(); mScroller.startScroll(getScrollX(), 0, -getScrollX(), 0, OPEN_ANIM_DURATION); invalidate();//这里必须调用invalidate()才能保证computeScroll()会被调用,否则不一定会刷新界面,看不到滚动效果 } private void clearScrollHis() { if (mScroller != null) { if (!mScroller.isFinished()) { mScroller.abortAnimation(); } } } /** * 根据现在的滚动位置判断 */ private void snapToDestation() { int scrollX = getScrollX(); if (scrollX > 0 && scrollX <= mLeftEdge) { smoothScrollTo(0); } else if (scrollX > mLeftEdge) { smoothScrollTo(mMaxScrollX); } } /** * 直接滚动 * * @param x * @return */ public boolean scrollTo(int x) { if (x < 0) { scrollTo(0, 0); } else if (x > mMaxScrollX) { scrollTo(mMaxScrollX, 0); } else { scrollTo(x, 0); } return true; } public void scrollToRight() { smoothScrollTo(mMaxScrollX); } public void scrollToLeft() { smoothScrollTo(0); } @Override protected void onScrollChanged(int l, int t, int oldl, int oldt) { super.onScrollChanged(l, t, oldl, oldt); Log.d(TAG, "left:" + l); if (l == 0) { Log.d(TAG, "OnFinish"); Toast.makeText(mContext, "Finished", Toast.LENGTH_SHORT).show(); if(mOnFinishListener!=null){ mOnFinishListener.onFinish(); } } } public void smoothScrollTo(int fx) { if (fx < 0) { smoothScrollTo(0, 0); } else if (fx > mMaxScrollX) { smoothScrollTo(mMaxScrollX, 0); } else { smoothScrollTo(fx, 0); } } // //调用此方法滚动到目标位置 public void smoothScrollTo(int fx, int fy) { int dx = fx - getScrollX(); int dy = fy - getScrollY(); smoothScrollBy(dx, dy); } //调用此方法设置滚动的相对偏移 public void smoothScrollBy(int dx, int dy) { //设置mScroller的滚动偏移量 mScroller.startScroll(getScrollX(), 0, dx, dy, Math.abs(dx * DURATION / mMaxScrollX)); invalidate();//这里必须调用invalidate()才能保证computeScroll()会被调用,否则不一定会刷新界面,看不到滚动效果 } @Override public void computeScroll() { //先判断mScroller滚动是否完成 if (mScroller.computeScrollOffset()) { //这里调用View的scrollTo()完成实际的滚动 scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); //必须调用该方法,否则不一定能看到滚动效果 postInvalidate(); } super.computeScroll(); } /** * fragment或者activity 结束的接口 */ public interface OnFinishListener{ void onFinish(); } }
以上就是本文的全部内容,希望对大家的学习有所帮助。
本文向大家介绍Android ViewPager实现左右滑动翻页效果,包括了Android ViewPager实现左右滑动翻页效果的使用技巧和注意事项,需要的朋友参考一下 本文实例为大家分享了ViewPager实现左右滑动翻页效果展示的具体代码,供大家参考,具体内容如下 代码如下: 布局文件: 以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。
本文向大家介绍Android组件banner实现左右滑屏效果,包括了Android组件banner实现左右滑屏效果的使用技巧和注意事项,需要的朋友参考一下 什么是banner组件?在许多Android应用上,比如爱奇艺客户端、百度美拍、应用宝等上面,都有一个可以手动滑动的小广告条,这就是banner,实际应用中的banner,其信息(图片和点击行为)是后台可配置的,是需要通过网络从后台拉取的。网上
实现右滑返回上个视图,滑动的时候具有视差效果。具体效果就是,向右滑动当前视图时,当前视图会往右滑动,当前视图的底部视图也会往右边滑动,但是当前视图滑动速度快于底部视图,从而造成一种视差效果(Parallax),当上面的视图滑动到最右边隐藏之后,底部的视图就完全露出来。 [Code4App.com]
本文向大家介绍Android实现微信首页左右滑动切换效果,包括了Android实现微信首页左右滑动切换效果的使用技巧和注意事项,需要的朋友参考一下 大家看到微信首页切换效果有没有觉得很炫,滑动切换,点击底部bar瞬间切换,滑动切换渐变效果,线上效果图: 之前也在博客上看到别人的实现,再次基础上,我做了些优化。首先说下实现原理,大神略过,o(╯□╰)o 页面上看到的三个页面是三个Fragment,
本文向大家介绍Android开发之使用150行代码实现滑动返回效果,包括了Android开发之使用150行代码实现滑动返回效果的使用技巧和注意事项,需要的朋友参考一下 今天带大家实现滑动返回效果.,具体内容如下所示: 先看看效果图: 因为没有具体内容,也没有简书的图片资源,所以稍微简陋了点. 但是依然不妨碍我们的效果展示~ OK,接下来惯例,通过阅读本文你能学习到: ViewDragHelper的
本文向大家介绍Android手势左右滑动效果,包括了Android手势左右滑动效果的使用技巧和注意事项,需要的朋友参考一下 最近想实现Android左滑弹出菜单框,右滑消失菜单这个个功能。了解了一下Android 的滑动事件,必须是在view组件或者Activity上实现,同时必须实现OnTouchListener, OnGestureListener这个两个接口。 以上就是本文的全部内容,希望对