天天看點

直播側滑清屏

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.ValueAnimator;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;

import java.util.ArrayList;

/**
 * 左滑 or 右滑清屏
 * @author chenpin
 */
public class ClearScreenLayout extends FrameLayout {
    /**手指按下的x軸位置*/
    private int mDownX;
    /**手指按下的y軸位置*/
    private int mDownY;
    /**滑動開始時x軸偏移量*/
    private int startX;
    /**目前x軸偏移量*/
    private int translateX;
    /**動畫結束時x軸偏移量*/
    private int endX;
    /**是否已清屏*/
    private boolean ifCleared;
    /**計算滑動速度*/
    private VelocityTracker mVelocityTracker;
    /**動畫*/
    private ValueAnimator mAnimator;
    /**true-左滑清屏 false-右滑清屏*/
    private boolean leftSlide = true;
    /**清屏監聽器*/
    private OnSlideClearListener slideClearListener;
    /**需要清除的View*/
    private ArrayList<View> listClearViews = new ArrayList<>();

    public ClearScreenLayout(Context context) {
        this(context, null);
    }

    public ClearScreenLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ClearScreenLayout(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        View view = new View(getContext());
        view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        view.setClickable(true);
        addView(view, 0);

        mVelocityTracker = VelocityTracker.obtain();
        mAnimator = ValueAnimator.ofFloat(0, 1.0f).setDuration(200);
        mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                float value = (float) valueAnimator.getAnimatedValue();
                translateChild((int) (translateX + value * (endX - translateX)));
            }
        });
        mAnimator.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                if (ifCleared && translateX == 0) {
                    if (slideClearListener != null) {
                        slideClearListener.onRestored();
                    }
                    ifCleared = !ifCleared;
                } else if (!ifCleared && Math.abs(translateX) == getWidth()) {
                    if (slideClearListener != null) {
                        slideClearListener.onCleared();
                    }
                    ifCleared = !ifCleared;
                }
            }
        });
    }

    /**
     * 滑動監聽
     */
    public void setOnSlideListener(OnSlideClearListener slideListener) {
        this.slideClearListener = slideListener;
    }

    /**
     * 滑動方向(左滑 or 右滑)
     */
    public void setSlideDirection(SlideDirection direction) {
        leftSlide = direction == SlideDirection.LEFT;
    }

    /**
     * 添加需要清屏的view
     */
    public void addClearViews(View... views) {
        for (View cell : views) {
            if (!listClearViews.contains(cell)) {
                listClearViews.add(cell);
            }
        }
    }

    /**
     * 移除需要清屏的view
     */
    public void removeClearViews(View... views) {
        for (View cell : views) {
            listClearViews.remove(cell);
        }
    }

    /**
     * 移除所有需要清屏的view
     */
    public void removeAllClearViews() {
        listClearViews.clear();
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        final int x = (int) event.getX();
        final int y = (int) event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mDownX = x;
                mDownY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                if (!mAnimator.isRunning() && Math.abs(x - mDownX) > Math.abs(y - mDownY)) {
                    startX = translateX;
                    if (x - mDownX < -10) {
                        if ((leftSlide && !ifCleared) || (!leftSlide && ifCleared)) {
                            return true;
                        }
                    } else if (x - mDownX > 10) {
                        if ((leftSlide && ifCleared) || (!leftSlide && !ifCleared)) {
                            return true;
                        }
                    }
                }
                break;
            default:
                break;
        }
        return super.onInterceptTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        mVelocityTracker.addMovement(event);
        final int x = (int) event.getX();
        final int offsetX = x - mDownX;
        switch (event.getAction()) {
            case MotionEvent.ACTION_MOVE:
                translateChild(startX + offsetX);
                return true;
            case MotionEvent.ACTION_UP:
                if (translateX != 0) {
                    mVelocityTracker.computeCurrentVelocity(10);
                    if (Math.abs(offsetX) > getWidth() / 3 ||
                            (mVelocityTracker.getXVelocity() > 20 && !leftSlide && !ifCleared) ||
                            (mVelocityTracker.getXVelocity() > 20 && leftSlide && ifCleared) ||
                            (mVelocityTracker.getXVelocity() < -20 && !leftSlide && ifCleared) ||
                            (mVelocityTracker.getXVelocity() < -20 && leftSlide && !ifCleared)) {
                        if (ifCleared) {
                            endX = 0;
                        } else if (leftSlide) {
                            endX = -getWidth();
                        } else {
                            endX = getWidth();
                        }
                    } else {
                        endX = startX;
                    }
                }
                mAnimator.start();
                return true;
            default:
                break;
        }
        return super.onTouchEvent(event);
    }

    private void translateChild(int translate) {
        if ((leftSlide && translate > 0) || ((!leftSlide && translate < 0))) {
            translate = 0;
        }
        translateX = translate;
        for (int i = 0; i < listClearViews.size(); i++) {
            listClearViews.get(i).setTranslationX(translate);
        }
    }

    public interface OnSlideClearListener {
        void onCleared();

        void onRestored();
    }

    public enum SlideDirection {
        LEFT, RIGHT
    }
}