FileDocCategorySizeDatePackage
DragDownHelper.javaAPI DocAndroid 5.1 API8458Thu Mar 12 22:22:42 GMT 2015com.android.systemui.statusbar

DragDownHelper

public class DragDownHelper extends Object implements com.android.systemui.Gefingerpoken
A utility class to enable the downward swipe on the lockscreen to go to the full shade and expand the notification where the drag started.

Fields Summary
private static final float
RUBBERBAND_FACTOR_EXPANDABLE
private static final float
RUBBERBAND_FACTOR_STATIC
private static final int
SPRING_BACK_ANIMATION_LENGTH_MS
private int
mMinDragDistance
private ExpandHelper.Callback
mCallback
private float
mInitialTouchX
private float
mInitialTouchY
private boolean
mDraggingDown
private float
mTouchSlop
private DragDownCallback
mDragDownCallback
private android.view.View
mHost
private final int[]
mTemp2
private boolean
mDraggedFarEnough
private ExpandableView
mStartingChild
private android.view.animation.Interpolator
mInterpolator
private float
mLastHeight
Constructors Summary
public DragDownHelper(android.content.Context context, android.view.View host, ExpandHelper.Callback callback, DragDownCallback dragDownCallback)


          
              
        mMinDragDistance = context.getResources().getDimensionPixelSize(
                R.dimen.keyguard_drag_down_min_distance);
        mInterpolator =
                AnimationUtils.loadInterpolator(context, android.R.interpolator.fast_out_slow_in);
        mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
        mCallback = callback;
        mDragDownCallback = dragDownCallback;
        mHost = host;
    
Methods Summary
private voidcancelExpansion(ExpandableView child)

        if (child.getActualHeight() == child.getMinHeight()) {
            return;
        }
        ObjectAnimator anim = ObjectAnimator.ofInt(child, "actualHeight",
                child.getActualHeight(), child.getMinHeight());
        anim.setInterpolator(mInterpolator);
        anim.setDuration(SPRING_BACK_ANIMATION_LENGTH_MS);
        anim.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                mCallback.setUserLockedChild(child, false);
            }
        });
        anim.start();
    
private voidcancelExpansion()

        ValueAnimator anim = ValueAnimator.ofFloat(mLastHeight, 0);
        anim.setInterpolator(mInterpolator);
        anim.setDuration(SPRING_BACK_ANIMATION_LENGTH_MS);
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                mDragDownCallback.setEmptyDragAmount((Float) animation.getAnimatedValue());
            }
        });
        anim.start();
    
private voidcaptureStartingChild(float x, float y)

        if (mStartingChild == null) {
            mStartingChild = findView(x, y);
            if (mStartingChild != null) {
                mCallback.setUserLockedChild(mStartingChild, true);
            }
        }
    
private ExpandableViewfindView(float x, float y)

        mHost.getLocationOnScreen(mTemp2);
        x += mTemp2[0];
        y += mTemp2[1];
        return mCallback.getChildAtRawPosition(x, y);
    
private voidhandleExpansion(float heightDelta, ExpandableView child)

        if (heightDelta < 0) {
            heightDelta = 0;
        }
        boolean expandable = child.isContentExpandable();
        float rubberbandFactor = expandable
                ? RUBBERBAND_FACTOR_EXPANDABLE
                : RUBBERBAND_FACTOR_STATIC;
        float rubberband = heightDelta * rubberbandFactor;
        if (expandable && (rubberband + child.getMinHeight()) > child.getMaxHeight()) {
            float overshoot = (rubberband + child.getMinHeight()) - child.getMaxHeight();
            overshoot *= (1 - RUBBERBAND_FACTOR_STATIC);
            rubberband -= overshoot;
        }
        child.setActualHeight((int) (child.getMinHeight() + rubberband));
    
public booleanonInterceptTouchEvent(android.view.MotionEvent event)

        final float x = event.getX();
        final float y = event.getY();

        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                mDraggedFarEnough = false;
                mDraggingDown = false;
                mStartingChild = null;
                mInitialTouchY = y;
                mInitialTouchX = x;
                break;

            case MotionEvent.ACTION_MOVE:
                final float h = y - mInitialTouchY;
                if (h > mTouchSlop && h > Math.abs(x - mInitialTouchX)) {
                    mDraggingDown = true;
                    captureStartingChild(mInitialTouchX, mInitialTouchY);
                    mInitialTouchY = y;
                    mInitialTouchX = x;
                    mDragDownCallback.onTouchSlopExceeded();
                    return true;
                }
                break;
        }
        return false;
    
public booleanonTouchEvent(android.view.MotionEvent event)

        if (!mDraggingDown) {
            return false;
        }
        final float x = event.getX();
        final float y = event.getY();

        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_MOVE:
                mLastHeight = y - mInitialTouchY;
                captureStartingChild(mInitialTouchX, mInitialTouchY);
                if (mStartingChild != null) {
                    handleExpansion(mLastHeight, mStartingChild);
                } else {
                    mDragDownCallback.setEmptyDragAmount(mLastHeight);
                }
                if (mLastHeight > mMinDragDistance) {
                    if (!mDraggedFarEnough) {
                        mDraggedFarEnough = true;
                        mDragDownCallback.onThresholdReached();
                    }
                } else {
                    if (mDraggedFarEnough) {
                        mDraggedFarEnough = false;
                        mDragDownCallback.onDragDownReset();
                    }
                }
                return true;
            case MotionEvent.ACTION_UP:
                if (mDraggedFarEnough && mDragDownCallback.onDraggedDown(mStartingChild,
                        (int) (y - mInitialTouchY))) {
                    if (mStartingChild == null) {
                        mDragDownCallback.setEmptyDragAmount(0f);
                    }
                    mDraggingDown = false;
                } else {
                    stopDragging();
                    return false;
                }
                break;
            case MotionEvent.ACTION_CANCEL:
                stopDragging();
                return false;
        }
        return false;
    
private voidstopDragging()

        if (mStartingChild != null) {
            cancelExpansion(mStartingChild);
        } else {
            cancelExpansion();
        }
        mDraggingDown = false;
        mDragDownCallback.onDragDownReset();