Android侧滑返回的实现
来源:互联网 发布:mac 设置屏幕待机时间 编辑:程序博客网 时间:2024/04/28 11:34
IOS有侧滑回退的功能,可以侧滑回退到上一个Activity,并且在侧滑时,底层的actvity是透明显示的。下面代码将实现该功能。
主要实现思路是让Activity的整个容器滑动。
package com.tjpld.tonglingsafetyandroid.customview;import java.util.LinkedList;import java.util.List;import android.app.Activity;import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Rect;import android.graphics.drawable.Drawable;import android.support.v4.view.ViewPager;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.view.ViewConfiguration;import android.view.ViewGroup;import android.widget.FrameLayout;import android.widget.Scroller;import com.tjpld.tonglingsafetyandroid.R;public class SwipeBackLayout extends FrameLayout { private static final String TAG = SwipeBackLayout.class.getSimpleName(); //放置Activity的View private View mContentView; //侧滑最小距离 private int mTouchSlop; //按下的位置 private int downX; private int downY; //当前的位置 private int tempX; private Scroller mScroller; private int viewWidth; //判断是否为滑动 private boolean isSilding; //是否完成 private boolean isFinish; //侧滑的阴影效果 private Drawable mShadowDrawable; private Activity mActivity; private List<ViewPager> mViewPagers = new LinkedList<ViewPager>(); public SwipeBackLayout(Context context, AttributeSet attrs) { this(context, attrs, 0); } public SwipeBackLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); //得到最小的距离 mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); //初始化滑动对象 mScroller = new Scroller(context); //初始化阴影资源 mShadowDrawable = getResources().getDrawable(R.drawable.shadow_left); } //对外部提供的接口 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(); //从外界传入的activity页面的底层容器,setContentView设置的View的父容 器 父容器一般都是ViewGroup ViewGroup decor = (ViewGroup) activity.getWindow().getDecorView(); //得到setContentView设置的View ViewGroup decorChild = (ViewGroup) decor.getChildAt(0);//设置它的背景色 decorChild.setBackgroundResource(background); //移除到之前父容器中的布局view decor.removeView(decorChild); //为当前页面父容器添加设置过背景色后的子view addView(decorChild); setContentView(decorChild); decor.addView(this); } //得到从外部传入的activity的布局容器 private void setContentView(View decorChild) { mContentView = (View) decorChild.getParent(); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { ViewPager mViewPager = getTouchViewPager(mViewPagers, ev); Log.i(TAG, "mViewPager = " + mViewPager); //判断是否拦截此次事件 if (mViewPager != null && mViewPager.getCurrentItem() != 0) { return super.onInterceptTouchEvent(ev); } switch (ev.getAction()) { //当只是按下去是,既非滑动事件,不对此事件做处理 case MotionEvent.ACTION_DOWN: downX = tempX = (int) ev.getRawX(); downY = (int) ev.getRawY(); break; //当移动时拦截次事件 调用onTouchEvent case MotionEvent.ACTION_MOVE: int moveX = (int) ev.getRawX(); //如果滑动的位置到我按下的位置之间的距离大于系统默认的最小距离 视为一次滑动 if (moveX - downX > mTouchSlop && Math.abs((int) ev.getRawY() - downY) < mTouchSlop) { return true; } break; } return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_MOVE: //点击事件发生的位置 int moveX = (int) event.getRawX(); //滑动的距离,tempX当前的位置,在拦截事件里进行了初始化,第一次是你按下的位置 int deltaX = tempX - moveX; //当前位置就是view滑动后的位置 tempX = moveX; //如果滑动后的位置到按下的位置 大于默认滑动距离 视为一次滑动 if (moveX - downX > mTouchSlop && Math.abs((int) event.getRawY() - downY) < mTouchSlop) { isSilding = true; } //如果是一次滑动的话,就让整个容器滑动 if (moveX - downX >= 0 && isSilding) { mContentView.scrollBy(deltaX, 0); } break; case MotionEvent.ACTION_UP: isSilding = false; //向右滑动,值是负的 所以是小于等于整个view的宽的1/2时 代表完成了一次滑动 触发事件 if (mContentView.getScrollX() <= -viewWidth / 2) { isFinish = true; scrollRight(); } else { scrollOrigin(); isFinish = false; } break; } return true; } private void getAlLViewPager(List<ViewPager> mViewPagers, ViewGroup parent) { int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { View child = parent.getChildAt(i); if (child instanceof ViewPager) { mViewPagers.add((ViewPager) child); } else if (child instanceof ViewGroup) { getAlLViewPager(mViewPagers, (ViewGroup) child); } } } private ViewPager getTouchViewPager(List<ViewPager> mViewPagers, MotionEvent ev) { if (mViewPagers == null || mViewPagers.size() == 0) { return null; } Rect mRect = new Rect(); for (ViewPager v : mViewPagers) { v.getHitRect(mRect); if (mRect.contains((int) ev.getX(), (int) ev.getY())) { return v; } } return null; } @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(); getAlLViewPager(mViewPagers, this); Log.i(TAG, "ViewPager size = " + mViewPagers.size()); } } @Override protected void dispatchDraw(Canvas canvas) { super.dispatchDraw(canvas); if (mShadowDrawable != null && mContentView != null) { int left = mContentView.getLeft() - mShadowDrawable.getIntrinsicWidth(); int right = left + mShadowDrawable.getIntrinsicWidth(); int top = mContentView.getTop(); int bottom = mContentView.getBottom(); mShadowDrawable.setBounds(left, top, right, bottom); mShadowDrawable.draw(canvas); } } //当滑动布局超过1/2抬手时,用户抬手,但用户认为这样算是完成了操作,接下来隐藏另一部分contentView的工作由系统完成 private void scrollRight() { //计算出剩余的宽度 向右换滑动mContentView.getScrollX()负值 final int delta = (viewWidth + mContentView.getScrollX());//参数,起止X,起止Y,目标X,目标Y,持续时间//同时会调用computeScoller共同完成滑动 mScroller.startScroll(mContentView.getScrollX(), 0, -delta + 1, 0, Math.abs(delta)); postInvalidate(); } private void scrollOrigin() { int delta = mContentView.getScrollX(); mScroller.startScroll(mContentView.getScrollX(), 0, -delta, 0, Math.abs(delta)); postInvalidate(); } @Override public void computeScroll() { if (mScroller.computeScrollOffset()) { mContentView.scrollTo(mScroller.getCurrX(), mScroller.getCurrY()); postInvalidate(); //完成滑动时销毁页面 if (mScroller.isFinished() && isFinish) { mActivity.finish(); } } }}
使用的时候让Activity继承SwipeBackActivity 这是一个空实现的Activity
public class SwipeBackActivity extends AppCompatActivity { protected SwipeBackLayout layout; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); layout = (SwipeBackLayout) LayoutInflater.from(this).inflate( R.layout.base, null); layout.attachToActivity(this); } @Override public void startActivity(Intent intent) { super.startActivity(intent); overridePendingTransition(R.anim.base_slide_right_in, R.anim.base_slide_remain); } // Press the back button in mobile phone @Override public void onBackPressed() { super.onBackPressed(); overridePendingTransition(0, R.anim.base_slide_right_out); //第一动画代表下一个即将出来的页的进入动画效果,第二个代表当前页的退出动画效果// overridePendingTransition(R.anim.base_slide_right_in,R.anim.base_slide_left_out ); }}
注意:在style中设置activity的容器层的(window层)ViewGroup的背景为透明
<style name="Theme.AppCompat.Translucent" parent="AppTheme"> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:colorBackgroundCacheHint">@null</item> <item name="android:windowIsTranslucent">true</item> <item name="android:windowAnimationStyle">@android:style/Animation</item> </style>
同时给activity的layout布局View设置背景background.否则会使整个页面为透明
0 0
- Android侧滑返回的实现
- 【Android】Activity右滑返回的实现
- 【Android】Activity右滑返回的实现
- Android 返回按钮的实现
- android 实现Activity的右滑返回效果
- Android实现类似IOS右滑返回的效果
- Android中SwipeBack右滑返回(手势返回)的实现
- Android中SwipeBack右滑返回(手势返回)的实现(带源码)
- android重写返回键,实现返回键的一些功能
- Android返回键功能的实现方法
- android 左上角返回上一级的实现
- Android实现Activity的滑动返回效果
- Android中实现返回桌面的代码
- Android返回顶部实现
- android如何实现双击返回键退出 的修正版
- Android 返回键实现home键的功能
- android实现系统的返回键和home键
- Android如何实现类似Gmail的标题栏返回
- Eclipse中的快捷键功能
- Java基础(13):异常
- java面试--String详解
- LightOJ - 1429 Assassin`s Creed (II)(二分图)
- 魔方程序建立
- Android侧滑返回的实现
- C语言中的中文处理的问题。
- XMPP基本应用一
- Criteria 的使用
- 动画代码
- HDU 2647Reward (拓扑排序)
- 二叉树
- 从头认识java-6.7 初始化与类的加载
- POJ 2524 Ubiquitous Religions