詹子聪 5 лет назад
Родитель
Сommit
17095840ee

+ 1 - 1
app/build.gradle

@@ -120,7 +120,7 @@ dependencies {
     implementation 'cn.jzvd:jiaozivideoplayer:7.4.2'
 
     // 右划销毁Activity,另外:sockeqwe/SwipeBack也可以参考
-    implementation 'com.aitangba:swipeback:1.0.3'
+    //implementation 'com.aitangba:swipeback:1.0.3'
     // 图片点击可以放大缩小
     implementation 'com.github.chrisbanes:PhotoView:1.2.6'
 }

+ 70 - 0
app/src/main/java/com/itant/shibei/base/SwipeBackActivity.java

@@ -0,0 +1,70 @@
+package com.itant.shibei.base;
+
+import android.graphics.Color;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.RelativeLayout;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import com.itant.shibei.widget.SwipeBackLayout;
+
+/**
+ * Created by Eric on 15/3/3.
+ */
+public class SwipeBackActivity extends AppCompatActivity implements SwipeBackLayout.SwipeBackListener {
+
+    private static final SwipeBackLayout.DragEdge DEFAULT_DRAG_EDGE = SwipeBackLayout.DragEdge.LEFT;
+
+    private SwipeBackLayout swipeBackLayout;
+    private ImageView ivShadow;
+
+    @Override
+    public void setContentView(int layoutResID) {
+        super.setContentView(getContainer());
+        View view = LayoutInflater.from(this).inflate(layoutResID, null);
+        swipeBackLayout.addView(view);
+    }
+
+    private View getContainer() {
+        RelativeLayout container = new RelativeLayout(this);
+        swipeBackLayout = new SwipeBackLayout(this);
+        swipeBackLayout.setDragEdge(DEFAULT_DRAG_EDGE);
+        swipeBackLayout.setOnSwipeBackListener(this);
+        ivShadow = new ImageView(this);
+        //getResources().getColor(R.color.black_p50)
+        ivShadow.setBackgroundColor(Color.parseColor("#7f000000"));
+        ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
+        container.addView(ivShadow, params);
+        container.addView(swipeBackLayout);
+        return container;
+    }
+
+    public void setEnableSwipe(boolean enableSwipe) {
+        swipeBackLayout.setEnablePullToBack(enableSwipe);
+    }
+
+    public void setDragEdge(SwipeBackLayout.DragEdge dragEdge) {
+        swipeBackLayout.setDragEdge(dragEdge);
+    }
+
+    public void setDragDirectMode(SwipeBackLayout.DragDirectMode dragDirectMode) {
+        swipeBackLayout.setDragDirectMode(dragDirectMode);
+    }
+
+    public SwipeBackLayout getSwipeBackLayout() {
+        return swipeBackLayout;
+    }
+
+    public void setOnFinishListener(SwipeBackLayout.OnFinishListener onFinishListener){
+        swipeBackLayout.setOnFinishListener(onFinishListener);
+    }
+
+    @Override
+    public void onViewPositionChanged(float fractionAnchor, float fractionScreen) {
+        ivShadow.setAlpha(1 - fractionScreen);
+    }
+
+}

+ 1 - 3
app/src/main/java/com/itant/shibei/ui/BeiApplication.java

@@ -2,7 +2,6 @@ package com.itant.shibei.ui;
 
 import android.app.Application;
 
-import com.aitangba.swipeback.ActivityLifecycleHelper;
 import com.itant.shibei.manager.PreferenceManager;
 import com.umeng.analytics.MobclickAgent;
 import com.umeng.commonsdk.UMConfigure;
@@ -19,8 +18,7 @@ public class BeiApplication extends Application {
     @Override
     public void onCreate() {
         super.onCreate();
-
-        registerActivityLifecycleCallbacks(ActivityLifecycleHelper.build());
+        //registerActivityLifecycleCallbacks(ActivityLifecycleHelper.build());
 
         PreferenceManager.getInstance().initPreference(this);
         RxActivityResult.register(this);

+ 7 - 3
app/src/main/java/com/itant/shibei/ui/home/goods/detail/MeizhiDetailActivity.java

@@ -3,11 +3,12 @@ package com.itant.shibei.ui.home.goods.detail;
 import android.os.Bundle;
 import android.text.TextUtils;
 
-import com.aitangba.swipeback.SwipeBackActivity;
 import com.bumptech.glide.Glide;
 import com.bumptech.glide.load.engine.DiskCacheStrategy;
 import com.bumptech.glide.request.RequestOptions;
 import com.itant.shibei.R;
+import com.itant.shibei.base.SwipeBackActivity;
+import com.itant.shibei.widget.SwipeBackLayout;
 
 import uk.co.senab.photoview.PhotoView;
 
@@ -25,6 +26,9 @@ public class MeizhiDetailActivity extends SwipeBackActivity {
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_meizhi_detail);
 
+        // 垂直滑动退出
+        setDragDirectMode(SwipeBackLayout.DragDirectMode.VERTICAL);
+
         pv_meizhi = findViewById(R.id.pv_meizhi);
         findViewById(R.id.iv_back).setOnClickListener(v -> onBackPressed());
 
@@ -33,8 +37,8 @@ public class MeizhiDetailActivity extends SwipeBackActivity {
             Glide.with(this)
                     .load(url)
                     .apply(new RequestOptions()
-                            .placeholder(R.mipmap.ic_launcher)
-                            .error(R.mipmap.ic_launcher)
+                            .placeholder(R.mipmap.logo_gray)
+                            .error(R.mipmap.logo_gray)
                             .diskCacheStrategy(DiskCacheStrategy.ALL))
                     // 缓存所有尺寸的图片
                     //.thumbnail( 0.1f )//先加载原图大小的十分之一

+ 563 - 0
app/src/main/java/com/itant/shibei/widget/SwipeBackLayout.java

@@ -0,0 +1,563 @@
+package com.itant.shibei.widget;
+
+import android.app.Activity;
+import android.content.Context;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.webkit.WebView;
+import android.widget.AbsListView;
+import android.widget.ScrollView;
+
+import androidx.core.view.ViewCompat;
+import androidx.customview.widget.ViewDragHelper;
+import androidx.viewpager.widget.ViewPager;
+
+/**
+ * Swipe or Pull to finish a Activity.
+ * <p/>
+ * This layout must be a root layout and contains only one direct child view.
+ * <p/>
+ * The activity must use a theme that with translucent style.
+ * <style name="Theme.Swipe.Back" parent="AppTheme">
+ * <item name="android:windowIsTranslucent">true</item>
+ * <item name="android:windowBackground">@android:color/transparent</item>
+ * </style>
+ * <p/>
+ * Created by Eric on 15/1/8.
+ */
+public class SwipeBackLayout extends ViewGroup {
+
+    private static final String TAG = "SwipeBackLayout";
+
+    public enum DragDirectMode {
+        EDGE,
+        VERTICAL,
+        HORIZONTAL
+    }
+
+    public enum DragEdge {
+        LEFT,
+
+        TOP,
+
+        RIGHT,
+
+        BOTTOM
+    }
+
+    private DragDirectMode dragDirectMode = DragDirectMode.EDGE;
+
+    private DragEdge dragEdge = DragEdge.TOP;
+
+    public void setDragEdge(DragEdge dragEdge) {
+        this.dragEdge = dragEdge;
+    }
+
+    public void setDragDirectMode(DragDirectMode dragDirectMode) {
+        this.dragDirectMode = dragDirectMode;
+        if (dragDirectMode == DragDirectMode.VERTICAL) {
+            this.dragEdge = DragEdge.TOP;
+        } else if (dragDirectMode == DragDirectMode.HORIZONTAL) {
+            this.dragEdge = DragEdge.LEFT;
+        }
+    }
+
+    private static final double AUTO_FINISHED_SPEED_LIMIT = 2000.0;
+
+    private ViewDragHelper viewDragHelper;
+
+    private View target;
+
+    private View scrollChild;
+
+    private int verticalDragRange = 0;
+
+    private int horizontalDragRange = 0;
+
+    private int draggingState = 0;
+
+    private int draggingOffset;
+
+    /**
+     * Whether allow to pull this layout.
+     */
+    private boolean enablePullToBack = true;
+
+    private static final float BACK_FACTOR = 0.5f;
+
+    /**
+     * the anchor of calling finish.
+     */
+    private float finishAnchor = 0;
+
+    /**
+     * Set the anchor of calling finish.
+     *
+     * @param offset
+     */
+    public void setFinishAnchor(float offset) {
+        finishAnchor = offset;
+    }
+
+    private boolean enableFlingBack = true;
+
+    /**
+     * Whether allow to finish activity by fling the layout.
+     *
+     * @param b
+     */
+    public void setEnableFlingBack(boolean b) {
+        enableFlingBack = b;
+    }
+
+    private SwipeBackListener swipeBackListener;
+
+    @Deprecated
+    public void setOnPullToBackListener(SwipeBackListener listener) {
+        swipeBackListener = listener;
+    }
+
+    public void setOnSwipeBackListener(SwipeBackListener listener) {
+        swipeBackListener = listener;
+    }
+
+    public SwipeBackLayout(Context context) {
+        this(context, null);
+    }
+
+    public SwipeBackLayout(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        viewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelperCallBack());
+        chkDragable();
+    }
+
+    /**
+     * This should be added first than any other setting, because it will overwrite the viewDragHelper
+     *
+     * @param onFinishListener listener for what to do when view reach the end
+     */
+    public void setOnFinishListener(OnFinishListener onFinishListener ) {
+        viewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelperCallBack(onFinishListener));
+    }
+
+    float lastY = 0;
+    float newY = 0;
+    float offsetY = 0;
+
+    float lastX = 0;
+    float newX = 0;
+    float offsetX = 0;
+
+    private void chkDragable() {
+        setOnTouchListener(new View.OnTouchListener() {
+            @Override
+            public boolean onTouch(View view, MotionEvent motionEvent) {
+
+                if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
+                    lastY = motionEvent.getRawY();
+                    lastX = motionEvent.getRawX();
+                } else if (motionEvent.getAction() == MotionEvent.ACTION_MOVE) {
+                    newY = motionEvent.getRawY();
+                    lastX = motionEvent.getRawX();
+
+                    offsetY = Math.abs(newY - lastY);
+                    lastY = newY;
+
+                    offsetX = Math.abs(newX - lastX);
+                    lastX = newX;
+
+                    switch (dragEdge) {
+                        case TOP:
+                        case BOTTOM:
+                            setEnablePullToBack(offsetY > offsetX);
+                        case LEFT:
+                        case RIGHT:
+                            setEnablePullToBack(offsetY < offsetX);
+                            break;
+                    }
+                }
+
+                return false;
+            }
+        });
+    }
+
+    public void setScrollChild(View view) {
+        scrollChild = view;
+    }
+
+    public void setEnablePullToBack(boolean b) {
+        enablePullToBack = b;
+        Log.i(TAG, "enablePullToBack:" + enablePullToBack);
+    }
+
+    private void ensureTarget() {
+        if (target == null) {
+            if (getChildCount() > 1) {
+                throw new IllegalStateException("SwipeBackLayout must contains only one direct child");
+            }
+            target = getChildAt(0);
+
+            if (scrollChild == null && target != null) {
+                if (target instanceof ViewGroup) {
+                    findScrollView((ViewGroup) target);
+                } else {
+                    scrollChild = target;
+                }
+
+            }
+        }
+    }
+
+    /**
+     * Find out the scrollable child view from a ViewGroup.
+     *
+     * @param viewGroup
+     */
+    private void findScrollView(ViewGroup viewGroup) {
+        scrollChild = viewGroup;
+        if (viewGroup.getChildCount() > 0) {
+            int count = viewGroup.getChildCount();
+            View child;
+            for (int i = 0; i < count; i++) {
+                child = viewGroup.getChildAt(i);
+                if (child instanceof AbsListView || child instanceof ScrollView || child instanceof ViewPager || child instanceof WebView) {
+                    scrollChild = child;
+                    return;
+                }
+            }
+        }
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        int width = getMeasuredWidth();
+        int height = getMeasuredHeight();
+        if (getChildCount() == 0) return;
+
+        View child = getChildAt(0);
+
+        int childWidth = width - getPaddingLeft() - getPaddingRight();
+        int childHeight = height - getPaddingTop() - getPaddingBottom();
+        int childLeft = getPaddingLeft();
+        int childTop = getPaddingTop();
+        int childRight = childLeft + childWidth;
+        int childBottom = childTop + childHeight;
+        child.layout(childLeft, childTop, childRight, childBottom);
+    }
+
+    @Override
+    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
+        if (getChildCount() > 1) {
+            throw new IllegalStateException("SwipeBackLayout must contains only one direct child.");
+        }
+
+        if (getChildCount() > 0) {
+            int measureWidth = MeasureSpec.makeMeasureSpec(getMeasuredWidth() - getPaddingLeft() - getPaddingRight(), MeasureSpec.EXACTLY);
+            int measureHeight = MeasureSpec.makeMeasureSpec(getMeasuredHeight() - getPaddingTop() - getPaddingBottom(), MeasureSpec.EXACTLY);
+            getChildAt(0).measure(measureWidth, measureHeight);
+        }
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+        verticalDragRange = h;
+        horizontalDragRange = w;
+
+        switch (dragEdge) {
+            case TOP:
+            case BOTTOM:
+                finishAnchor = finishAnchor > 0 ? finishAnchor : verticalDragRange * BACK_FACTOR;
+                break;
+            case LEFT:
+            case RIGHT:
+                finishAnchor = finishAnchor > 0 ? finishAnchor : horizontalDragRange * BACK_FACTOR;
+                break;
+        }
+    }
+
+    private int getDragRange() {
+        switch (dragEdge) {
+            case TOP:
+            case BOTTOM:
+                return verticalDragRange;
+            case LEFT:
+            case RIGHT:
+                return horizontalDragRange;
+            default:
+                return verticalDragRange;
+        }
+    }
+
+    @Override
+    public boolean onInterceptTouchEvent(MotionEvent ev) {
+        boolean handled = false;
+        ensureTarget();
+        if (isEnabled()) {
+            handled = viewDragHelper.shouldInterceptTouchEvent(ev);
+        } else {
+            viewDragHelper.cancel();
+        }
+        return !handled ? super.onInterceptTouchEvent(ev) : handled;
+    }
+
+    @Override
+    public boolean onTouchEvent(MotionEvent event) {
+        viewDragHelper.processTouchEvent(event);
+        return true;
+    }
+
+    @Override
+    public void computeScroll() {
+        if (viewDragHelper.continueSettling(true)) {
+            ViewCompat.postInvalidateOnAnimation(this);
+        }
+    }
+
+    public boolean canChildScrollUp() {
+        return ViewCompat.canScrollVertically(scrollChild, -1);
+    }
+
+    public boolean canChildScrollDown() {
+        return ViewCompat.canScrollVertically(scrollChild, 1);
+    }
+
+    private boolean canChildScrollRight() {
+        return ViewCompat.canScrollHorizontally(scrollChild, -1);
+    }
+
+    private boolean canChildScrollLeft() {
+        return ViewCompat.canScrollHorizontally(scrollChild, 1);
+    }
+
+    private void finish() {
+        Activity act = (Activity) getContext();
+        act.finish();
+        act.overridePendingTransition(0, android.R.anim.fade_out);
+    }
+
+    private class ViewDragHelperCallBack extends ViewDragHelper.Callback {
+
+        private OnFinishListener onFinishListener = new OnFinishListener() {
+            @Override
+            public void onFinishState() {
+                finish();
+            }
+        };
+
+        public ViewDragHelperCallBack() {
+        }
+
+        public ViewDragHelperCallBack(OnFinishListener onFinishListener) {
+            this.onFinishListener = onFinishListener;
+        }
+
+        @Override
+        public boolean tryCaptureView(View child, int pointerId) {
+            return child == target && enablePullToBack;
+        }
+
+        @Override
+        public int getViewVerticalDragRange(View child) {
+            return verticalDragRange;
+        }
+
+        @Override
+        public int getViewHorizontalDragRange(View child) {
+            return horizontalDragRange;
+        }
+
+        @Override
+        public int clampViewPositionVertical(View child, int top, int dy) {
+
+            int result = 0;
+
+            if (dragDirectMode == DragDirectMode.VERTICAL) {
+                if (!canChildScrollUp() && top > 0) {
+                    dragEdge = DragEdge.TOP;
+                } else if (!canChildScrollDown() && top < 0) {
+                    dragEdge = DragEdge.BOTTOM;
+                }
+            }
+
+            if (dragEdge == DragEdge.TOP && !canChildScrollUp() && top > 0) {
+                final int topBound = getPaddingTop();
+                final int bottomBound = verticalDragRange;
+                result = Math.min(Math.max(top, topBound), bottomBound);
+            } else if (dragEdge == DragEdge.BOTTOM && !canChildScrollDown() && top < 0) {
+                final int topBound = -verticalDragRange;
+                final int bottomBound = getPaddingTop();
+                result = Math.min(Math.max(top, topBound), bottomBound);
+            }
+
+            return result;
+        }
+
+        @Override
+        public int clampViewPositionHorizontal(View child, int left, int dx) {
+
+            int result = 0;
+
+            if (dragDirectMode == DragDirectMode.HORIZONTAL) {
+                if (!canChildScrollRight() && left > 0) {
+                    dragEdge = DragEdge.LEFT;
+                } else if (!canChildScrollLeft() && left < 0) {
+                    dragEdge = DragEdge.RIGHT;
+                }
+            }
+
+            if (dragEdge == DragEdge.LEFT && !canChildScrollRight() && left > 0) {
+                final int leftBound = getPaddingLeft();
+                final int rightBound = horizontalDragRange;
+                result = Math.min(Math.max(left, leftBound), rightBound);
+            } else if (dragEdge == DragEdge.RIGHT && !canChildScrollLeft() && left < 0) {
+                final int leftBound = -horizontalDragRange;
+                final int rightBound = getPaddingLeft();
+                result = Math.min(Math.max(left, leftBound), rightBound);
+            }
+
+            return result;
+        }
+
+        @Override
+        public void onViewDragStateChanged(int state) {
+            if (state == draggingState) {
+                return;
+            }
+
+            if ((draggingState == ViewDragHelper.STATE_DRAGGING || draggingState == ViewDragHelper.STATE_SETTLING) &&
+                    state == ViewDragHelper.STATE_IDLE) {
+                // the view stopped from moving.
+                if (draggingOffset == getDragRange()) {
+                    onFinishListener.onFinishState();
+                }
+            }
+
+            draggingState = state;
+        }
+
+        @Override
+        public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
+            switch (dragEdge) {
+                case TOP:
+                case BOTTOM:
+                    draggingOffset = Math.abs(top);
+                    break;
+                case LEFT:
+                case RIGHT:
+                    draggingOffset = Math.abs(left);
+                    break;
+                default:
+                    break;
+            }
+
+            //The proportion of the sliding.
+            float fractionAnchor = (float) draggingOffset / finishAnchor;
+            if (fractionAnchor >= 1) {
+                fractionAnchor = 1;
+            }
+
+            float fractionScreen = (float) draggingOffset / (float) getDragRange();
+            if (fractionScreen >= 1) {
+                fractionScreen = 1;
+            }
+
+            if (swipeBackListener != null) {
+                swipeBackListener.onViewPositionChanged(fractionAnchor, fractionScreen);
+            }
+        }
+
+        @Override
+        public void onViewReleased(View releasedChild, float xvel, float yvel) {
+            if (draggingOffset == 0) return;
+
+            if (draggingOffset == getDragRange()) return;
+
+            boolean isBack = false;
+
+            if (enableFlingBack && backBySpeed(xvel, yvel)) {
+                isBack = !canChildScrollUp();
+            } else if (draggingOffset >= finishAnchor) {
+                isBack = true;
+            } else if (draggingOffset < finishAnchor) {
+                isBack = false;
+            }
+
+            int finalLeft;
+            int finalTop;
+            switch (dragEdge) {
+                case LEFT:
+                    finalLeft = isBack ? horizontalDragRange : 0;
+                    smoothScrollToX(finalLeft);
+                    break;
+                case RIGHT:
+                    finalLeft = isBack ? -horizontalDragRange : 0;
+                    smoothScrollToX(finalLeft);
+                    break;
+                case TOP:
+                    finalTop = isBack ? verticalDragRange : 0;
+                    smoothScrollToY(finalTop);
+                    break;
+                case BOTTOM:
+                    finalTop = isBack ? -verticalDragRange : 0;
+                    smoothScrollToY(finalTop);
+                    break;
+            }
+
+        }
+    }
+
+    private boolean backBySpeed(float xvel, float yvel) {
+        switch (dragEdge) {
+            case TOP:
+            case BOTTOM:
+                if (Math.abs(yvel) > Math.abs(xvel) && Math.abs(yvel) > AUTO_FINISHED_SPEED_LIMIT) {
+                    return dragEdge == DragEdge.TOP ? !canChildScrollUp() : !canChildScrollDown();
+                }
+                break;
+            case LEFT:
+            case RIGHT:
+                if (Math.abs(xvel) > Math.abs(yvel) && Math.abs(xvel) > AUTO_FINISHED_SPEED_LIMIT) {
+                    return dragEdge == DragEdge.LEFT ? !canChildScrollLeft() : !canChildScrollRight();
+                }
+                break;
+        }
+        return false;
+    }
+
+    private void smoothScrollToX(int finalLeft) {
+        if (viewDragHelper.settleCapturedViewAt(finalLeft, 0)) {
+            ViewCompat.postInvalidateOnAnimation(SwipeBackLayout.this);
+        }
+    }
+
+    private void smoothScrollToY(int finalTop) {
+        if (viewDragHelper.settleCapturedViewAt(0, finalTop)) {
+            ViewCompat.postInvalidateOnAnimation(SwipeBackLayout.this);
+        }
+    }
+
+    public interface OnFinishListener {
+
+        void onFinishState();
+    }
+
+    public interface SwipeBackListener {
+
+        /**
+         * Return scrolled fraction of the layout.
+         *
+         * @param fractionAnchor relative to the anchor.
+         * @param fractionScreen relative to the screen.
+         */
+        void onViewPositionChanged(float fractionAnchor, float fractionScreen);
+
+    }
+
+}

+ 2 - 1
app/src/main/res/layout/activity_meizhi_detail.xml

@@ -20,5 +20,6 @@
         android:id="@+id/pv_meizhi"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:src="@mipmap/logo_gray" />
+        android:src="@mipmap/logo_gray"
+        android:scaleType="centerInside"/>
 </LinearLayout>