最近公司需求要做一个分享解锁的功能,其中有一个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<ResolveInfo> 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