Android全屏右滑移除界面,可设置忽略控件防止滑动冲突

 

hello大家好,2018快结束了,掐指一算才发现自己才写了两篇博客,年初定下的目标也只完成了一半。不是不想写,只是不知道写些什么,不过好在快把《明朝那些事儿》看完了,有兴趣的话我们一起交流交流吧~

说会正题,最近项目提了一个新需求,就是在界面上实现全屏右滑返回效果。老板说,这个效果别人APP都有,我们也要。IOS端倒好,系统提供了侧滑返回事件,只需监听屏幕滑动位置来回调侧滑返回事件即可实现效果。没办法,既然都提了肯定有办法解决。老规矩,先来看看我的实现效果吧:

其实已经有人已经写好了,效果还非常的不错,感兴趣的可以Star一下:SwipeBackLayout

其实实现起来非常简单,只需要获取当前屏幕的DecorView,然后监听dispatchTouchEvent事件,来根据滑动距离来偏移DecorView,当左右滑动的时候禁用ScrollView的上下滑动。可能你们已经发现了,顶部还有一个轮播图控件,这样一来不会造成滑动冲突吗?答案是会的,但是我们可以通过按下的位置来判断当前按下的是否是设置忽略的控件。来看代码吧,注释很详细,我相信你能看懂~

**
 * Created by fySpring
 * Date : 2018-11-15
 * To do :继承你的BaseActivity,或者直接继承AppCompatActivity
 */

public class BaseSlideActivity extends BaseActivity {

    //该控件子控件中包含ConvenientBanner的集合 ,也可以放别的控件
    private List<ConvenientBanner> mViewPagers = new LinkedList<>();

    View decorView;
    int screenWidth;//屏宽
    CustomScrollView combineSv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //获取屏幕的宽度以及底层的View
        decorView = getWindow().getDecorView();
        DisplayMetrics metrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(metrics);
        screenWidth = metrics.widthPixels;
    }

    float startX, startY, endX, endY, distanceX, distanceY;

    //当前按下的是ConvenientBanner
    boolean isTouchC = false;
    //当前按下的是ScrollView
    boolean isTouchS = false;
    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                startX = event.getX();
                startY = event.getY();
                ConvenientBanner cb = getTouchViewPager(event);
                if (cb != null) {
                    //当前按下的是ConvenientBanner,不拦截
                    isTouchC = true;
                    isTouchS = false;
                    return super.dispatchTouchEvent(event);
                } else {
                    isTouchC = false;
                    isTouchS = true;
                }
                break;
            case MotionEvent.ACTION_MOVE:
                endX = event.getX();
                endY = event.getY();
                distanceX = endX - startX;
                distanceY = Math.abs(endY - startY);

                if (isTouchC) {
                    //当手指移动过程中,按下的是ConvenientBanner,不能进行屏幕偏移
                    return super.dispatchTouchEvent(event);
                } else {
                    //1.判断手势右滑  2.横向滑动的距离要大于竖向滑动的距离
                    if (endX - startX > 0 && distanceY < distanceX && isTouchS) {
                        decorView.setX(distanceX);
                        //禁用ScrollView的竖直滑动事件
                        if (combineSv != null) combineSv.setScrollFlag(true);
                    }
                }

                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:

                if (isTouchC) {
                    isTouchC = false;
                    return super.dispatchTouchEvent(event);
                } else {
                    isTouchS = false;
                    endX = event.getX();
                    distanceX = endX - startX;
                    endY = event.getY();
                    distanceY = Math.abs(endY - startY);
                    //1.判断手势右滑  2.横向滑动的距离要大于竖向滑动的距离 3.横向滑动距离大于屏幕三分之一才能finish
                    if (endX - startX > 0 && distanceY < distanceX && distanceX > screenWidth / 3) {
                        moveOn(distanceX);
                    } else if (endX - startX > 0 && distanceY < distanceX) {
                        //1.判断手势右滑  2.横向滑动的距离要大于竖向滑动的距离 但是横向滑动距离不够则返回原位置
                        backOrigin(distanceX);
                    } else {
                        decorView.setX(0);
                    }
                    if (combineSv != null) combineSv.setScrollFlag(false);
                }
                break;
        }
        return super.dispatchTouchEvent(event);
    }


    /**
     * 设置忽略左滑的ConvenientBanner控件
     */
    public void setViewPagers(List<ConvenientBanner> mViewPagers) {
        this.mViewPagers = mViewPagers;
    }

    public void setCombineSv(CustomScrollView combineSv) {
        this.combineSv = combineSv;
    }

    /**
     * 通过点击的位置判断是否等于我所设置的控件位置
     *
     * @param ev 触摸事件
     * @return 当前触摸的ConvenientBanner
     */
    private ConvenientBanner getTouchViewPager(MotionEvent ev) {
        if (mViewPagers == null || mViewPagers.isEmpty()) {
            return null;
        }
        Rect mRect = new Rect();
        int[] location = new int[2];
        for (ConvenientBanner v : mViewPagers) {
            v.getLocationInWindow(location);
            mRect.set(location[0], location[1], location[0] + v.getMeasuredWidth(), location[1] + v.getMeasuredHeight());
            if (mRect.contains((int) ev.getX(), (int) ev.getY())) {
                return v;
            }
        }
        return null;
    }

    /**
     * 返回原点
     *
     * @param distanceX 横向滑动距离
     */
    private void backOrigin(float distanceX) {
        ObjectAnimator.ofFloat(decorView, "X", distanceX, 0).setDuration(300).start();
    }

    /**
     * 划出屏幕
     *
     * @param distanceX 横向滑动距离
     */
    private void moveOn(float distanceX) {
        ValueAnimator valueAnimator = ValueAnimator.ofFloat(distanceX, screenWidth);
        valueAnimator.setDuration(300);
        valueAnimator.start();

        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                decorView.setX((Float) animation.getAnimatedValue());
            }
        });

        valueAnimator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animation) {

            }

            @Override
            public void onAnimationEnd(Animator animation) {
                finish();
            }

            @Override
            public void onAnimationCancel(Animator animation) {

            }

            @Override
            public void onAnimationRepeat(Animator animation) {

            }
        });
    }
}

记得为你的Activity设置一个透明主题。

<style name="SlideTheme" parent="AppTheme">
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:colorBackgroundCacheHint">@null</item>
        <item name="android:windowIsTranslucent">true</item>
    </style>
<activity
            android:name=".activities.GoodsDetailActivity"
            android:theme="@style/SlideTheme" />

好了,就是以上这些代码,如果有左右滑动的控件,记得在外面设置进去。有问题的话欢迎留言~接下来我要去完成我的目标了,嘿嘿

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

斯普润丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值