ViewDragHelper 这个滑动帮助类 网上一找一大堆的介绍 就不多赘述了
在项目中遇到一个双指滑动 出现侧边栏 侧边栏还是个最近使用的功能列表
在写的时候出现两个重要的问题,第一个就是滑动冲突,第二个就是standard自启后
h5界面无效的问题
看一下xml 的基础结构
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".view.WebviewActivity">
<com.tencent.tinyapp.view.customview.DragViewGroup
android:id="@+id/view"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<FrameLayout
android:visibility="gone"
android:background="@color/colorGray2"
android:layout_width="500dp"
android:layout_height="match_parent"
>
<TextView
android:id="@+id/tv_ceshi"
android:gravity="center"
android:layout_marginLeft="@dimen/dp_17"
android:textSize="@dimen/sp_40"
android:textColor="@color/colorWhite"
android:layout_width="wrap_content"
android:layout_height="@dimen/dp_55"
android:text="最近使用" />
<FrameLayout
android:id="@+id/recently_root"
android:layout_marginTop="@dimen/dp_55"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:background="@color/colorGray"
android:id="@+id/toolbar_webview"
android:layout_width="match_parent"
android:layout_height="@dimen/dp_55"
android:orientation="horizontal"
>
<ImageView
android:layout_marginLeft="@dimen/dp_24"
android:id="@+id/iv_webtitale"
android:background="@drawable/back"
android:layout_width="@dimen/dp_55"
android:layout_height="@dimen/dp_55"/>
<TextView
android:layout_marginLeft="@dimen/dp_24"
android:id="@+id/wv_title"
android:textSize="@dimen/sp_40"
android:textColor="@color/colorWhite"
android:text="标题"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
<com.tencent.jsbridge.BridgeWebView
android:layout_marginTop="@dimen/dp_55"
android:layout_below="@id/toolbar_webview"
android:id="@+id/webview_show"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
</com.tencent.tinyapp.view.customview.DragViewGroup>
<!-- <com.tencent.smtt.sdk.WebView-->
<!-- android:id="@+id/webview_show"-->
<!-- android:layout_width="match_parent"-->
<!-- android:layout_height="match_parent"-->
<!-- android:layout_marginTop="48dp"-->
<!-- app:layout_constraintLeft_toLeftOf="parent"-->
<!-- app:layout_constraintTop_toBottomOf="@id/toolbar_webview" />-->
</RelativeLayout>
自定义drag类
public class DragViewGroup extends FrameLayout {
private ViewDragHelper mViewDragHelper;
private View mMenuView, mMainView;
private int mWidth;
private int oldX1 = 0, oldX2 = 0, oldY1 = 0, oldY2 = 0, newX1 = 0, newY1 = 0, newX2 = 0, newY2 = 0, mScrollPointerId1, mScrollPointerId2;
private BridgeWebView web;
private FrameLayout root;
public DragViewGroup(Context context) {
super(context);
initView();
}
public DragViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
initView();
}
public DragViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initView();
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mMenuView = getChildAt(0);
mMainView = getChildAt(1);
web = mMainView.findViewById(R.id.webview_show);
root = mMenuView.findViewById(R.id.recently_root);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
mWidth = mMenuView.getMeasuredWidth();
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
int pointerCount = ev.getPointerCount();
if (pointerCount==1)return false;
return mViewDragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent event) {
// 将触摸事件传递给ViewDragHelper,此操作必不可少
// int pointerCount = event.getPointerCount();
// if (pointerCount==1){
//// 单指事件传递给web
// web.onTouchEvent(event);
// return false;
// }
mViewDragHelper.processTouchEvent(event);
return true;
}
private void initView() {
mViewDragHelper = ViewDragHelper.create(this, callback);
}
private ViewDragHelper.Callback callback = new ViewDragHelper.Callback() {
// 何时开始检测触摸事件
@Override
public boolean tryCaptureView(View child, int pointerId) {
Log.d("sss","pointerId"+pointerId);
// if (pointerId==0)return false;//过滤单指
// else if (pointerId==1){
return mMainView == child;
// }
// 如果当前触摸的child是mMainView时开始检测
// return false;
}
// 触摸到View后回调
@Override
public void onViewCaptured(View capturedChild, int activePointerId) {
super.onViewCaptured(capturedChild, 2);
}
// 当拖拽状态改变,比如idle,dragging
@Override
public void onViewDragStateChanged(int state) {
super.onViewDragStateChanged(state);
}
// 当位置改变的时候调用,常用与滑动时更改scale等
@Override
public void onViewPositionChanged(View changedView, int left, int top,
int dx, int dy) {
super.onViewPositionChanged(changedView, left, top, dx, dy);
}
// 处理垂直滑动
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
return 0;
}
// 处理水平滑动
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
if (left > 0) {
// 如果手势向右滑动则返回,如果向左滑动不返回
mMenuView.setVisibility(VISIBLE);
return left;
}
return 0;
}
@Override
public int getViewHorizontalDragRange(@NonNull View child) {
return 1;
}
// 拖动结束后调用
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
super.onViewReleased(releasedChild, xvel, yvel);
// 手指抬起后缓慢移动到指定位置
if (mMainView.getLeft() < 500) {
// 关闭菜单
// 相当于Scroller的startScroll方法
mViewDragHelper.smoothSlideViewTo(mMainView, 0, 0);
mMenuView.setVisibility(GONE);
ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
} else {
// 打开菜单
mViewDragHelper.smoothSlideViewTo(mMainView, 800, 0);
ViewCompat.postInvalidateOnAnimation(DragViewGroup.this);
}
}
};
@Override
public void computeScroll() {
if (mViewDragHelper.continueSettling(true)) {
ViewCompat.postInvalidateOnAnimation(this);
}
}
}
这里解决冲突问题 主要还是onInterceptTouchEvent 事件拦截方法里面 设置单指不拦截 双指拦截交给
viewDraghelper去处理就可以了
问题二 就是侧滑打开了最近使用的一个fragment界面 但是最近使用的都是h5的小程序 所以启动还是自己
如果用栈内复用和栈顶模式都是不可以跳转其他h5界面的 因为onNewIntent的缘故,所以需要设置standard
启动模式!那么设置这个模式问题又来了 第二个界面覆盖第一个界面的时候 一旦返回 直接返回第一个界面
而第一个界面的h5页面就会失去点击功能 具体情况不清楚 所以我做了任务栈处理来解决这个问题,不管开几个界面 最终返回的时候都回退到上一层界面 把所有的standard启动的自己 全部弹出任务栈
简单版本的 TaskUtils
public class ActivityStack {
private static volatile ActivityStack mInstance;
private LinkedList<Activity> mActivityList;
public ActivityStack() {
this.mActivityList = new LinkedList<>();
}
public static ActivityStack getInstance(){
if (mInstance==null){
synchronized (ActivityStack.class){
if (mInstance==null){
mInstance=new ActivityStack();
}
}
}
return mInstance;
}
public void addActivity2Stack(Activity activity){
mActivityList.add(activity);
}
public void removeActivity2Stack(Activity activity){
mActivityList.remove(activity);
}
public void finishAll(){
for (Activity activity : mActivityList) {
activity.finish();
}
}
}
然后在自启界面的onResume 中add 当前activity实例 在需要退出的地方 finishAll 即可
网友评论