@Override protected void onFinishInflate() { super.onFinishInflate(); mHandleView = findViewById(R.id.handle); loadDimens(); if (DEBUG) LOG("handle view: " + mHandleView); if (mHandleView != null) { mHandleView.setOnTouchListener( new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { final float y = event.getY(); final float rawY = event.getRawY(); if (DEBUG) LOG( "handle.onTouch: a=%s y=%.1f rawY=%.1f off=%.1f", MotionEvent.actionToString(event.getAction()), y, rawY, mTouchOffset); PanelView.this.getLocationOnScreen(mAbsPos); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mTracking = true; mHandleView.setPressed(true); postInvalidate(); // catch the press state change mInitialTouchY = y; mVelocityTracker = VelocityTracker.obtain(); trackMovement(event); mTimeAnimator.cancel(); // end any outstanding animations mBar.onTrackingStarted(PanelView.this); mTouchOffset = (rawY - mAbsPos[1]) - PanelView.this.getExpandedHeight(); if (mExpandedHeight == 0) { mJustPeeked = true; runPeekAnimation(); } break; case MotionEvent.ACTION_MOVE: final float h = rawY - mAbsPos[1] - mTouchOffset; if (h > mPeekHeight) { if (mPeekAnimator != null && mPeekAnimator.isRunning()) { mPeekAnimator.cancel(); } mJustPeeked = false; } if (!mJustPeeked) { PanelView.this.setExpandedHeightInternal(h); mBar.panelExpansionChanged(PanelView.this, mExpandedFraction); } trackMovement(event); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: mFinalTouchY = y; mTracking = false; mHandleView.setPressed(false); postInvalidate(); // catch the press state change mBar.onTrackingStopped(PanelView.this); trackMovement(event); float vel = 0, yVel = 0, xVel = 0; boolean negative = false; if (mVelocityTracker != null) { // the velocitytracker might be null if we got a bad input stream mVelocityTracker.computeCurrentVelocity(1000); yVel = mVelocityTracker.getYVelocity(); negative = yVel < 0; xVel = mVelocityTracker.getXVelocity(); if (xVel < 0) { xVel = -xVel; } if (xVel > mFlingGestureMaxXVelocityPx) { xVel = mFlingGestureMaxXVelocityPx; // limit how much we care about the x axis } vel = (float) Math.hypot(yVel, xVel); if (vel > mFlingGestureMaxOutputVelocityPx) { vel = mFlingGestureMaxOutputVelocityPx; } mVelocityTracker.recycle(); mVelocityTracker = null; } // if you've barely moved your finger, we treat the velocity as 0 // preventing spurious flings due to touch screen jitter final float deltaY = Math.abs(mFinalTouchY - mInitialTouchY); if (deltaY < mFlingGestureMinDistPx || vel < mFlingExpandMinVelocityPx) { vel = 0; } if (negative) { vel = -vel; } if (DEBUG) LOG("gesture: dy=%f vel=(%f,%f) vlinear=%f", deltaY, xVel, yVel, vel); fling(vel, true); break; } return true; } }); } }