com.baoyz.dribble.widget.SwipeHoverLayout.java Source code

Java tutorial

Introduction

Here is the source code for com.baoyz.dribble.widget.SwipeHoverLayout.java

Source

/*
 * The MIT License (MIT)
 * 
 * Copyright (c) 2015 baoyongzhang <baoyz94@gmail.com>
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.baoyz.dribble.widget;

import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.support.v4.view.GestureDetectorCompat;
import android.support.v4.view.MotionEventCompat;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.widget.RelativeLayout;

import com.baoyz.dribble.R;
import com.baoyz.dribble.util.DimenUtil;
import com.daimajia.androidviewhover.tools.Blur;
import com.daimajia.androidviewhover.tools.Util;

/**
 * Created by baoyz on 15/1/19.
 */
public class SwipeHoverLayout extends RelativeLayout {

    public static final int ANIMATION_DURATION = 500;

    private int mScrollDistance;
    private int mCanScrollDistance;
    private int mFlingVelocity;
    private GestureDetectorCompat mGestureDetector;

    private boolean mFlingShow;
    private boolean mDistanceShow;
    private int mDownX;
    private int mMaxDistance;
    private int mTouchSlop;

    private int mHoverState = HoverState.HIDE;

    private View mHoverView;

    static class HoverState {
        public static final int HIDE = 0x0000;
        public static final int SHOW = ~HIDE;
    }

    public SwipeHoverLayout(Context context) {
        super(context);
        init();
    }

    public SwipeHoverLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public SwipeHoverLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public SwipeHoverLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init() {

        ViewConfiguration viewConfiguration = ViewConfiguration.get(getContext());
        mScrollDistance = DimenUtil.dp2px(getContext(), 60);
        mCanScrollDistance = viewConfiguration.getScaledOverscrollDistance();
        mFlingVelocity = viewConfiguration.getScaledMinimumFlingVelocity();
        mTouchSlop = viewConfiguration.getScaledTouchSlop();

        mGestureDetector = new GestureDetectorCompat(getContext(), new GestureDetector.SimpleOnGestureListener() {

            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                mFlingShow = Math.abs(velocityX) >= mFlingVelocity;
                return false;
            }

            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                int distance = Math.abs((int) (e2.getX() - mDownX));
                mDistanceShow = distance >= 10;
                dispatchSwipe(distance);
                return false;
            }

            @Override
            public boolean onDown(MotionEvent e) {
                mDownX = (int) e.getX();
                mFlingShow = false;
                mDistanceShow = false;
                return true;
            }
        });
    }

    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        mHoverView = findViewById(R.id.hoverView);
        mHoverView.setVisibility(View.GONE);
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        mMaxDistance = w;
    }

    private void dispatchSwipe(int distance) {
        if (distance < mCanScrollDistance)
            return;
        float percent = (float) distance / mMaxDistance;
        switch (mHoverState) {
        case HoverState.HIDE:
            swipeShow(percent);
            break;
        case HoverState.SHOW:
            swipeHide(percent);
            break;
        }
    }

    private void swipeHide(float percent) {
        ensureHoverView();
        mHoverView.setAlpha(1 - percent);
    }

    private void swipeShow(float percent) {
        ensureHoverView();
        mHoverView.setAlpha(percent);
    }

    private void startSmoothAnimation(final int state) {
        if (mHoverState == state)
            return;
        ensureHoverView();
        switch (state) {
        case HoverState.HIDE:
            mHoverView.animate().alpha(0f).setDuration(ANIMATION_DURATION)
                    .setListener(new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            super.onAnimationEnd(animation);
                            mHoverState = state;
                            destroyHover();
                        }
                    }).start();
            break;
        case HoverState.SHOW:
            mHoverView.animate().alpha(1f).setDuration(ANIMATION_DURATION)
                    .setListener(new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            super.onAnimationEnd(animation);
                            mHoverState = state;
                        }
                    }).start();
            break;
        }
    }

    private void ensureHoverView() {
        if (mHoverView.getVisibility() == View.GONE) {
            mHoverView.setVisibility(View.VISIBLE);
            mHoverView.setBackgroundDrawable(generateBlurDrawable());
            mHoverView.setAlpha(0f);
        }
        if (mHoverView.getParent() == null) {
            //            addView(mHoverView);
        }
    }

    private Drawable generateBlurDrawable() {
        return new BitmapDrawable(getResources(), Blur.apply(getContext(), Util.getViewBitmap(this)));
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        int actionMasked = MotionEventCompat.getActionMasked(ev);
        boolean flag = false;
        switch (actionMasked) {
        case MotionEvent.ACTION_DOWN:
            mDownX = (int) ev.getX();
            mGestureDetector.onTouchEvent(ev);
            break;
        case MotionEvent.ACTION_MOVE:
            if (Math.abs(ev.getX() - mDownX) > mTouchSlop)
                flag = true;
            break;
        }
        return flag;
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        boolean flag = mGestureDetector.onTouchEvent(ev);
        int actionMasked = MotionEventCompat.getActionMasked(ev);
        switch (actionMasked) {
        case MotionEvent.ACTION_CANCEL:
            startSmoothAnimation(mHoverState);
            mDistanceShow = false;
            mFlingShow = false;
            break;
        case MotionEvent.ACTION_UP:
            if (mDistanceShow || mFlingShow) {
                startSmoothAnimation(~mHoverState);
            } else {
                startSmoothAnimation(mHoverState);
            }
            mDistanceShow = false;
            mFlingShow = false;
            break;
        }
        return flag;
    }

    public View getHoverView() {
        return mHoverView;
    }

    public void destroyHover() {
        if (getHoverView().getVisibility() == View.VISIBLE) {
            getHoverView().setBackgroundDrawable(null);
            getHoverView().setVisibility(View.GONE);
        }
    }
}