Java tutorial
/* * 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); } } }