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 即可