仿咔叽分享页层级滑动效果

最近公司需求要做一个分享解锁的功能,其中有一个more按钮是调用系统分享app的,具体是这样的:

  Intent shareIntent = new Intent();
  shareIntent.setAction(Intent.ACTION_SEND);
  shareIntent.setType("text/plain");
  shareIntent.putExtra(Intent.EXTRA_TEXT, extra);
  startActivityForResult(Intent.createChooser(shareIntent, "发送"), 100);

这样就可以调用系统的分享页面,并且把extra分享出去,但是这样去做就无法捕获到底有没有点击分享出去,虽然自己写分享页面也没法确切的知道,但是至少可以进一步保障。
以下是获取系统中含有分享功能的app:

 PackageManager pm = getPackageManager();
 Intent intent = new Intent(Intent.ACTION_SEND, null);
 intent.setType("text/plain");
 List list = pm.queryIntentActivities(intent, PackageManager.COMPONENT_ENABLED_STATE_DEFAULT);

list就是获取到的系统分享,包括蓝牙、短信等系统app。

接下来进入主题,一个滑动层级的问题,主要功能是外面一个framelayout,里面包含一个recyclerview,然后初始显示的时候framelayout显示默认高度,然后滑动的时候先将framelayout滑动到固定高度,然后再来触发recyclerview的滑动机制,其实主要原理就是解决滑动先后,事件传递要非常了解,这块有问题的同学可以去看看touch事件传递。
项目中我自定义了一个recyclerview,还有一个framelayout,以便于可以修改滑动事件的传递流程:

ShareRecyclerView 的主要代码:

private float downY = -1, pointY = -1;

@Override
public boolean onTouchEvent(MotionEvent e) {
    switch (e.getAction()) {
        case MotionEvent.ACTION_DOWN:
            downY = e.getRawY();
            pointY = e.getRawY();
            mShareLayout.setPointYFromChild(pointY);
            break;
        case MotionEvent.ACTION_MOVE:
            if (pointY == -1) {
                pointY = e.getRawY();
                downY = pointY;
                mShareLayout.setPointYFromChild(e.getRawY());
                return super.onTouchEvent(e);
            }
            boolean touch;
            if (mShareLayout != null) {
                touch = mShareLayout.isEnableTouch(e.getRawY() < pointY);
                if (touch) {
                    mShareLayout.move(e);
                    mShareLayout.setPointYFromChild(pointY);
                } else {
                    mShareLayout.setPointYFromChild(e.getRawY());
                    super.onTouchEvent(e);
                }
            }
            pointY = e.getRawY();
            return true;
        case MotionEvent.ACTION_UP:
            //同步点击后up的z坐标数据
            if (mShareLayout != null) {
                mShareLayout.up(e);
            }
            pointY = -1;
            downY = -1;
            return false;
        case MotionEvent.ACTION_CANCEL:
            pointY = -1;
            downY = -1;
            break;
    }
    return super.onTouchEvent(e);
}

public boolean onTouchUp(MotionEvent e) {
    return super.onTouchEvent(e);
}

public boolean onTouchCancel(MotionEvent e) {
    e.setAction(MotionEvent.ACTION_CANCEL);
    return super.onTouchEvent(e);
}

ShareBottomLayout的主要代码

@Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                if (vTracker == null) {
                    vTracker = VelocityTracker.obtain();
                } else {
                    vTracker.clear();
                }
                vTracker.addMovement(event);
                pointX = downX = event.getX();
                pointY = downY = event.getY();
                moved = false;
                return true;
            case MotionEvent.ACTION_MOVE:
                if (vTracker == null) {
                    vTracker = VelocityTracker.obtain();
                }
                vTracker.addMovement(event);
                vTracker.computeCurrentVelocity(1000);
                if (pointY == -1) {
                    pointY = event.getY();
                    return false;
                }
                if (!isPointEnable(event.getX(), event.getY()) && !moved) {
                    pointY = event.getY();
                    return false;
                }
                moved = true;
                if (event.getY() < pointY) {
                    LayoutParams params = (LayoutParams) content.getLayoutParams();
                    if (params.height >= maxHeight) {
                        pointY = event.getY();
                        if (mRecyclerView.canScrollVertically(1)) {
                            return true;
                        }
                    } else {
                        int height = (int) (params.height + pointY - event.getY());
                        setLayoutHeight(height);
                        pointY = event.getY();
                        return true;
                    }
                } else {
                    if (mRecyclerView.canScrollVertically(-1)) {
                        pointY = event.getY();
                        mRecyclerView.onTouchEvent(event);
                        return true;
                    }
                    LayoutParams params = (LayoutParams) content.getLayoutParams();
                    int height = (int) (params.height + pointY - event.getY());
                    setLayoutHeight(height);
                    pointY = event.getY();
                    return true;
                }
            case MotionEvent.ACTION_UP:
                if (!moved && !isPointEnable(downX, downY) && !isPointEnable(pointX, pointY)) {
                    dismiss();
                    return true;
                }

                LayoutParams params = (LayoutParams) content.getLayoutParams();
                if (params.height < initHeight) {
                    dismiss();
                } else if (vTracker != null && vTracker.getYVelocity() < -1000) {
                    scrollToInit(params.height, maxHeight);
                } else if (params.height > initHeight && params.height < maxHeight) {
                    scrollToInit(params.height, initHeight);
                }
                break;
        }
        return super.onTouchEvent(event);
    }

主要思路是系统会默认调用Recyclerview的touchdown方法去记录按下的点位置,然后调用recyclerview的move事件,去判断如果父类可以滑动(没有滑动到最大的高度),如果没有的话则return true ,然后调用父类的处理方法(这里父类的处理方式是逐步的增加他的高度)。

这里有几个坑:
1.滑动的时候必须用e.getRawY(),不然的话recyclerview和framelayout的滑动事件点是不一样的
2.滑动framelayout的时候也要调用recyclerview的ontouch的up或者cacel方法,不然可能有第一次无法点击item的问题。

写的可能有点low,经供参考。

最后附上github地址:https://github.com/luyongdong/scrolllayerview.git

你可能感兴趣的:(仿咔叽分享页层级滑动效果)